[mootools]セレクトメニューを連動させて動的に選択肢を変更する

セレクトメニューが2つあって、1つ目のセレクトメニューを選択したら、その値によって2つ目のセレクトメニューの選択肢を入れ替えるというものです。
わざわざ何番煎じか分からないネタを遇えて取り上げたのは、巷でよく見かける「配列にデータを入れて出力する」という方法ではなく、Validなソースでこれをやりたかったためです。
選択肢がやたらと多くなりがちなもの、たとえば県から市を選んだりするフォームなどでよく使われていると思います。
とりあえずセレクトメニュー2つだけ連動させてみました。

XHTML

連動させるセレクトメニューにそれぞれIDが必要。
親セレクトメニューのoption要素につけたクラス名と、子セレクトメニューのoptgroup要素のクラス名を同じにします。
optgroup内に入れた要素が選択された時に入れ替わる選択肢になります。

<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のコアファイルを読み込んでおかないと動きません。

window.addEvent('domready', function(){
	new SelectSelector($("select"),{change:"select2"});
});

new SelectSelector( $(select ID), { change:"select2 ID"});
最初が親になるセレクトメニュー、その次が子になるセレクトメニューのID。両方とも必須。

mootools Class

jsファイルにコピーしたりscriptタグ内に貼り付けたりしてください。

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);
			});
		});
	}
});

やってることの大まかな流れ

  1. 親セレクトメニュー(以下、親)と子セレクトメニュー(以下、子)を取得
  2. 子のoptgroupを取得し、さらにその子要素であるoption要素の複製を作って
    連想配列(hash)に{class:option}の形式で格納。
  3. 子のoptgroupを削除してから「選択してください」を入れる
  4. 親が選択されたら、選択されたoption要素のclass名を取得。
    連想配列からclass名をキーに持つ値を取得してクローン作成。
  5. 取得した要素は配列なので、eachで処理して子に追加。

なんでクローン作るの?と思ったらまずclone()消して試してみてください。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください