年齢計算フォーム

今の年齢を自動計算してくれるスクリプトです。
フォームを作るに当たって、selectタグのinnerHTMLに書き込もうとしたら、FirefoxではうまくいくのにIEでは動きませんでした。それを直すためにDOMを使っています。参考ソースは以下の通りです。

スポンサーリンク


別のサイトで下のような選択フォームを作りました

1月、3月、5月、7月、8月、10月、12月は日付を31日まで選択できますが、
4月、6月、9月、11月は30日まで、2月は年によって28日か29日になります。
(西暦は大正元年にあたる1912年まで対応)

誤入力を防止するため、存在しない日付は表示しません。

たとえば、今年、今月を選択すれば、1日から今日の日付までしか選べません。

昭和64年は1月7日までなので、昭和64年1月を選べば7日まで、平成元年1月を選べば
8日からの表示となります。

元号年から西暦への変換も出来ます。
たとえば平成1年を選択した後に、西暦を押すと1989年と表示されます。

これを実現するのに以下のソースを書いてFirefoxで試したらうまくいきました。
ところが、IE(インターネット エクスプローラー)ではset_select関数が動きません。

Internet ExplorerではselectタグのinnerHTMLへの挿入はサポートしていないそうです。

フォーム

<!-- 起動するまでdisplay:noneで非表示にして、誤作動防止 -->
<form id="age_form" style="display:none;text-align:center">
<p style="color:#00f;font-weight:bold">年齢計算フォーム</p>
<p>
<input type="radio" name="gengou" onclick="gengou_changed(this)" checked="checked" />
西暦&nbsp;&nbsp;
<input type="radio" name="gengou" onclick="gengou_changed(this)" />
平成&nbsp;&nbsp;
<input type="radio" name="gengou" onclick="gengou_changed(this)" />
昭和&nbsp;&nbsp;
<input type="radio" name="gengou" onclick="gengou_changed(this)" />
大正
</p>
<select onchange="year_changed(this)">
<option value="0">---</option>
</select>
年
<select onchange="month_changed(this)">
<option value="0">---</option>
</select>
月
<select onchange="day_changed(this)">
<option value="0">---</option>
</select>
日
&nbsp;<span></span>
</form>

スクリプト

var today=new Date();
var taisyou_gannen=1912;

//これだとIEでは動きません
var set_select=function(select,min,max,diff){
	var option=select.getElementsByTagName('option');
	var selected=parseInt(option[select.selectedIndex].value,10);

	select.innerHTML='<option value="0">---</option>';

	if(!min&&!max){
		return;
	}

	for(;min<=max;min++){
		var num=min+diff;
		var attr=num==selected?' selected="selected" ':'';

		select.innerHTML+=
			'<option value="'+num+'"'+attr+'>'+min+'</option>';
	}
}

var is_urudoshi=function(year){ //閏年ならtrue
	if(year%4){
		return false;
	}

	if(year%100){
		return true;
	}

	if(year%400){
		return false;
	}

	return true;
}

var day_changed=function(elem){
	var select=elem.parentNode.getElementsByTagName('select');
	var span=elem.parentNode.getElementsByTagName('span');

	if(select.length!=3||span.length!=1){return;}

	var option=select[2].getElementsByTagName('option');
	var day=parseInt(option[select[2].selectedIndex].value,10);

	if(!day){
		span[0].innerHTML='';
		return;
	}

	option=select[1].getElementsByTagName('option');
	var month=parseInt(option[select[1].selectedIndex].value,10);

	option=select[0].getElementsByTagName('option');
	var year=parseInt(option[select[0].selectedIndex].value,10);

	//現在の年齢を算出
	var today_num=(today.getFullYear()*10000)
			+((today.getMonth()+1)*100)+today.getDate();
	var age=Math.floor((today_num-
			((year*10000)+(month*100)+day))/10000);

	span[0].innerHTML='現在の年齢:'+age+'歳';
}

var month_changed=function(elem){
	var input=elem.parentNode.getElementsByTagName('input');
	var select=elem.parentNode.getElementsByTagName('select');

	if(input.length!=4||select.length!=3){return;}

	var option=select[1].getElementsByTagName('option');
	var month=parseInt(option[select[1].selectedIndex].value,10);

	option=select[0].getElementsByTagName('option');
	var year=parseInt(option[select[0].selectedIndex].value,10);

	//誤作動防止のため最大範囲(1~31)で初期化
	set_select(select[2],1,31,0);

	if(!month){
		//月が「---」なら日も「---」
		set_select(select[2],0,0,0);
	}else if(year==1989&&month==1&&input[1].checked){
		//平成元年は1月8日から
		set_select(select[2],8,31,0);
	}else if(year==1989&&month==1&&input[2].checked){
		//昭和64年は1月7日まで
		set_select(select[2],1,7,0);
	}else if(year==1926&&month==12&&input[2].checked){
		//昭和元年は12月25日から
		set_select(select[2],25,31,0);
	}else if(year==1926&&month==12&&input[3].checked){
		//大正15年は12月25日まで
		//大正最後の日と昭和最初の日は同じ
		set_select(select[2],1,25,0);
	}else if(year==1912&&month==7&&input[3].checked){
		//大正元年は7月30日から
		set_select(select[2],30,31,0);
	}else if(year==today.getFullYear()&&month==today.getMonth()+1){
		//今年の今月なら今日まで表示
		set_select(select[2],1,today.getDate(),0);
	}else if(month==2){
		if(is_urudoshi(year)){
			//閏年の2月は29日まで
			set_select(select[2],1,29,0);
		}else{
			//それ以外の2月は28日まで
			set_select(select[2],1,28,0);
		}
	}else if(month==4||month==6||month==9||month==11){
		//4、6、9、11月は30日まで
		set_select(select[2],1,30,0);
	}

	day_changed(elem);
}

var year_changed=function(elem){
	var input=elem.parentNode.getElementsByTagName('input');
	var select=elem.parentNode.getElementsByTagName('select');

	if(input.length!=4||select.length!=3){return;}

	var option=select[0].getElementsByTagName('option');
	var year=parseInt(option[select[0].selectedIndex].value,10);

	//誤作動防止のため最大範囲(1~12)で初期化
	set_select(select[1],1,12,0);

	if(!year){
		//年が「---」なら月も「---」
		set_select(select[1],0,0,0);
	}else if(year==today.getFullYear()){
		//今年なら今月まで表示
		set_select(select[1],1,today.getMonth()+1,0);
	}else if(input[2].checked){
		if(year==1989){
			//昭和64年は1月まで(よって平成元年も1月から)
			set_select(select[1],1,1,0);
		}else if(year==1926){
			//昭和元年は12月から
			set_select(select[1],12,12,0);
		}
	}else if(input[3].checked&&year==1912){
		//大正元年は7月から
		//大正のそれ以外の年はすべて1~12月まである
		set_select(select[1],7,12,0);
	}

	month_changed(elem);
}

var gengou_changed=function(elem){
	var input=elem.parentNode.getElementsByTagName('input');
	var select=
		elem.parentNode.parentNode.getElementsByTagName('select');

	if(input.length!=4||select.length!=3){return;}

	for(var i=0;i<input.length;i++){
		if(input[i].checked){
			//誤作動防止のため最大範囲で初期化
			set_select(select[0],
				taisyou_gannen,today.getFullYear(),0);

			if(i==1){
				//平成元年から今年まで
				set_select(select[0],
					1,today.getFullYear()-1988,1988);
			}else if(i==2){
				//昭和元年から64年まで
				set_select(select[0],1,64,1925);
			}else if(i==3){
				//大正元年から15年まで
				set_select(select[0],1,15,1911);
			}

			break;
		}
	}

	year_changed(select[0]);
}

var load_event=function(){
	var elem=document.getElementById('age_form');
	if(!elem){return;}

	var select=elem.getElementsByTagName('select');
	if(select.length!=3){return;}

	set_select(select[0],taisyou_gannen,today.getFullYear(),0);
	elem.style.display='block'; //フォームを表示
}

// 詳細は別記事「addEventListenerとattachEvent」を見てください
if(window.addEventListener){
	window.addEventListener('load', load_event, false);
}else if(window.attachEvent){
	window.attachEvent('onload', load_event);
}

IEに対応させるためにDOMを使って、set_select関数のソースを書き直したらうまく動きました。

var set_select=function(select,min,max,diff){
	var option=select.getElementsByTagName('option');
	var cnt=parseInt(option[option.length-1].value,10)-diff;

	//maxまでなければ追加

	while(max>cnt){
		cnt++;
		var elem=document.createElement('option');
		elem.setAttribute('value',cnt+diff);
		//optionへのinnerHTMLは書き込み可能
		elem.innerHTML=cnt;
		select.appendChild(elem);
	}

	//max以上あったら削除

	while(max<cnt){
		select.removeChild(option[option.length-1]);
		cnt--;
	}

	cnt=option.length==1?0:parseInt(option[1].value,10)-diff;

	//min以下があったら削除

	while(min>cnt){
		select.removeChild(option[1]);
		cnt++;
	}

	//minまでなければ追加

	while(min<cnt){
		cnt--;
		var elem=document.createElement('option');
		elem.setAttribute('value',cnt+diff);
		//optionへのinnerHTMLは書き込み可能
		elem.innerHTML=cnt;
		select.insertBefore(elem,
				select.getElementsByTagName('option')[1]);
	}

	option=select.getElementsByTagName('option');

	for(var i=1;i<option.length;i++){
		//optionへのinnerHTMLは書き込み可能
		option[i].innerHTML=min++;
	}
}

関連コンテンツ

スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。

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