セレクトメニューが2つあって、1つ目のセレクトメニューを選択したら、その値によって2つ目のセレクトメニューの選択肢を入れ替えるというものです。
わざわざ何番煎じか分からないネタを遇えて取り上げたのは、巷でよく見かける「配列にデータを入れて出力する」という方法ではなく、Validなソースでこれをやりたかったためです。
選択肢がやたらと多くなりがちなもの、たとえば県から市を選んだりするフォームなどでよく使われていると思います。
とりあえずセレクトメニュー2つだけ連動させてみました。
XHTML
連動させるセレクトメニューにそれぞれIDが必要。
親セレクトメニューのoption要素につけたクラス名と、子セレクトメニューのoptgroup要素のクラス名を同じにします。
optgroup内に入れた要素が選択された時に入れ替わる選択肢になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | < label for = "select" >選択肢1</ label > < select name = "select" id = "select" > < option value = "果物" class = "fruit" >果物</ option > < option value = "肉" class = "meat" >肉</ option > < option value = "魚" class = "fish" >魚</ option > </ select > < label for = "select2" >選択肢2</ label > < select name = "select2" id = "select2" > < optgroup class = "fruit" label = "果物" > < option value = "リンゴ" selected = "selected" >リンゴ</ option > < option value = "みかん" >みかん</ option > < option value = "ぶどう" >ぶどう</ option > < option value = "桃" >桃</ option > </ optgroup > < optgroup class = "meat" label = "肉" > < option value = "m1" >牛肉</ option > < option value = "m2" >豚肉</ option > < option value = "m3" >鶏肉</ option > </ optgroup > < optgroup class = "fish" label = "魚" > < option value = "maguro" >マグロ</ option > < option value = "sisyamo" >ししゃも</ option > < option value = "iwashi" >イワシ</ option > < option value = "sanma" >サンマ</ option > </ optgroup > </ select > |
見ての通り普通にソース書くのとそう変わらんので、javscriptオフでもフォームは機能します。
option要素を持たないselectを作る必要もないからバリデートに怒られる心配もない。
optgroupのラベルはどっちでもいい。
Javscript
headとかで事前にmootools ver1.2のコアファイルを読み込んでおかないと動きません。
1 2 3 | window.addEvent( 'domready' , function (){ new SelectSelector($( "select" ),{change: "select2" }); }); |
new SelectSelector( $(select ID), { change:"select2 ID"});
最初が親になるセレクトメニュー、その次が子になるセレクトメニューのID。両方とも必須。
mootools Class
jsファイルにコピーしたりscriptタグ内に貼り付けたりしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | var SelectSelector = new Class({ Implements: [Options,Events], options: { change: null }, initialize: function (element,options) { this .setOptions(options); this .element = element; //select1 this .change = $( this .options.change); //select2 this .groups = this .change.getChildren(); //optgroup this .array = new Hash(); this .groups.each( function (item,index){ this .array.set(item.getProperty( 'class' ), item.getChildren().clone()); }.bind( this )); this .start(); }, start: function () { var self = this ; this .groups.destroy(); this .change.grab( new Element( "option" ,{text: "選択してください" })); this .element.addEvent( "change" , function (e){ var key = self.element.getSelected().getProperty( 'class' ); var opt = self.array.get(key[0]).clone(); self.change.getChildren().destroy(); opt.each( function (item, index){ self.change.grab(item); }); }); } }); |
やってることの大まかな流れ
- 親セレクトメニュー(以下、親)と子セレクトメニュー(以下、子)を取得
- 子のoptgroupを取得し、さらにその子要素であるoption要素の複製を作って
連想配列(hash)に{class:option}の形式で格納。 - 子のoptgroupを削除してから「選択してください」を入れる
- 親が選択されたら、選択されたoption要素のclass名を取得。
連想配列からclass名をキーに持つ値を取得してクローン作成。 - 取得した要素は配列なので、eachで処理して子に追加。
なんでクローン作るの?と思ったらまずclone()消して試してみてください。