セレクトボックス同士の連動

セレクトボックスのある値を選択すると、別のセレクトボックスがその値に応じて内容が変わるスクリプトをご紹介します。
ここでご紹介するセレクトボックスの連動は、1対1を対象としています。

元のセレクトボックスのvalue属性値とoptgroupのlabel属性値を比較して一致したものを表示するような仕組みです。

デモ

 

関数定義とHTMLの準備

関数定義

JavaScript

var linkedSelect = function() {
	this.init.apply(this, arguments);
};

linkedSelect.prototype = {

	settings : {},
	elements : {},
	data     : {},

	init : function(settings) {

		settings = this.arrayMerge({
			actionTargetName  : '',
			changeTargetName  : '',
			stockFirstElement : true
		}, settings);
		this.settings = settings;

		this.data = {
			activeIndex : 0
		};

		if (settings.actionTargetName && settings.changeTargetName) {
			this.setup();
		}

		return this;
	},

	setup : function() {
		var actionTargetElements = document.getElementsByName(this.settings.actionTargetName),
		    changeTargetElements = document.getElementsByName(this.settings.changeTargetName);

		if (actionTargetElements.length > 0 && changeTargetElements.length > 0) {
			var actionTargetElement = actionTargetElements[0],
			    changeTargetElement = changeTargetElements[0],
			    optionGroups        = changeTargetElement.getElementsByTagName('optgroup'),
			    optionElementObjs   = [],
			    optionElements      = [],
			    optionCloneElements = [],
			    attrNode            = null,
			    selectIndex         = 0,
			    ii                  = 0,
			    len2                = 0;

			for (var i = 0, len = optionGroups.length; i < len; i++) {
				optionElements      = optionGroups[i].getElementsByTagName('option');
				optionCloneElements = [];
				selectIndex         = 0;

				for (ii = 0, len2 = optionElements.length; ii < len2; ii++) {
					attrNode = optionElements[ii].getAttributeNode('selected');

					if (attrNode) {
						selectIndex = ii;
						optionElements[ii].removeAttribute(attrNode);
					}

					optionCloneElements.push(optionElements[ii].cloneNode(true));
				}

				optionElementObjs.push({
					label       : optionGroups[i].label,
					elements    : optionCloneElements,
					selectIndex : selectIndex
				});

			}

			var stockFirstElement = changeTargetElement.getElementsByTagName('option')[0].cloneNode(true);
			changeTargetElement.innerHTML = '';

			if (this.settings.stockFirstElement) {
				changeTargetElement.appendChild(stockFirstElement);
			}

			this.elements = {
				changeTargetElement : changeTargetElement,
				actionTargetElement : actionTargetElement,
				optionElements      : optionElementObjs
			};

			this.addEvent();
			this.changeOption();
		}

		return this;
	},

	addEvent : function() {
		var self = this;

		if (!this.elements.actionTargetElement) return this;

		this.elements.actionTargetElement.onchange = function() {
			self.changeOption();
		};

		return this;
	},

	changeOption : function() {
		if (this.elements.actionTargetElement && this.elements.changeTargetElement && this.elements.optionElements) {
			var actionTargetElement     = this.elements.actionTargetElement,
			    changeTargetElement     = this.elements.changeTargetElement,
			    optionElements          = this.elements.optionElements,
			    oldSelectIndex          = this.data.activeIndex,
			    selectIndex             = actionTargetElement.selectedIndex,
			    changeTargetSelectIndex = changeTargetElement.selectedIndex,
			    options                 = actionTargetElement.options,
			    selectValue             = options[selectIndex].value,
			    setSelected             = 0,
			    oldOptionElements       = null,
			    stockFirstElement       = '',
			    setOptions              = [],
			    i                       = 0,
			    len                     = 0;

			this.data.activeIndex = selectIndex;

			if (this.settings.stockFirstElement) {
				stockFirstElement = changeTargetElement.getElementsByTagName('option')[0].cloneNode(true);
				changeTargetElement.innerHTML = '';
				changeTargetElement.appendChild(stockFirstElement);
				oldSelectIndex--;
			} else {
				changeTargetElement.innerHTML = '';
			}

			if (oldSelectIndex > -1) {
				oldOptionElements = optionElements[oldSelectIndex];
				oldOptionElements.selectIndex = changeTargetSelectIndex;
			}

			if (selectValue !== '') {
				for (i = 0, len = optionElements.length; i < len; i++) {
					if (optionElements[i].label === selectValue) {
						setSelected = optionElements[i].selectIndex;
						setOptions  = optionElements[i].elements;
						break;
					}
				}

				for (i = 0, len = setOptions.length; i < len; i++) {
					changeTargetElement.appendChild(setOptions[i]);
				}
				changeTargetElement.selectedIndex = setSelected;
			}
		}
		return this;
	},

	arrayMerge : function() {
		var key, result = false;

		if (arguments && arguments.length > 0) {
			result = {};
			for (var i = 0, len = arguments.length;i < len; i++) {
				if (arguments[i] && typeof arguments[i] === 'object') {
					for (key in arguments[i]) {
						if (isFinite(key)) {
							result.push(arguments[i][key]);
						} else {
							result[key] = arguments[i][key];
						}
					}
				}
			}
		}

		return result;
	}
};

HTMLの準備

label属性には切り替え元のターゲットであるoptionのvalue値を指定します。

<p><select name="sample-linked-select1">
	<option value="select 1">select 1</option>
	<option value="select 2">select 2</option>
	<option value="select 3">select 3</option>
	<option value="select 4">select 4</option>
	<option value="select 5">select 5</option>
</select> <select name="sample-linked-select2">
	<optgroup label="select 1">
		<option value="select 1-1">select 1-1</option>
		<option value="select 1-2">select 1-2</option>
		<option value="select 1-3">select 1-3</option>
		<option value="select 1-4">select 1-4</option>
		<option value="select 1-5">select 1-5</option>
	</optgroup>
	<optgroup label="select 2">
		<option value="select 2-1">select 2-1</option>
		<option value="select 2-2">select 2-2</option>
		<option value="select 2-3">select 2-3</option>
		<option value="select 2-4">select 2-4</option>
		<option value="select 2-5">select 2-5</option>
	</optgroup>
	<optgroup label="select 3">
		<option value="select 3-1">select 3-1</option>
		<option value="select 3-2">select 3-2</option>
		<option value="select 3-3">select 3-3</option>
		<option value="select 3-4">select 3-4</option>
		<option value="select 3-5">select 3-5</option>
	</optgroup>
	<optgroup label="select 4">
		<option value="select 4-1">select 4-1</option>
		<option value="select 4-2">select 4-2</option>
		<option value="select 4-3">select 4-3</option>
		<option value="select 4-4">select 4-4</option>
		<option value="select 4-5">select 4-5</option>
	</optgroup>
	<optgroup label="select 5">
		<option value="select 5-1">select 5-1</option>
		<option value="select 5-2">select 5-2</option>
		<option value="select 5-3">select 5-3</option>
		<option value="select 5-4">select 5-4</option>
		<option value="select 5-5">select 5-5</option>
	</optgroup>
</select></p>

使い方

構文

var instance = new linkedSelect(options);

引数

引数名 説明
第一引数
必須
options object 各種設定
オプションを参照

オプション

設定値 初期値 説明
actionTargetName '' アクションを起こすセレクトボックスのname属性値
changeTargetName '' option要素を切り替えるセレクトボックスのname属性値
stockFirstElement true option要素を切り替えるセレクトボックスの最初の要素を維持するかどうか

サンプルコード

var linkedSelectObj = new linkedSelect({
	actionTargetName : 'first',
	changeTargetName : 'sub'
});

JavaScript逆引きリファレンス一覧へ戻る