緯度:<input type="text" name="latitude"> <input type="hidden" name="data[latitude]" value="<?php h(_d($data,'latitude'))?>""><br> 経度:<input type="text" name="longitude"> <input type="hidden" name="data[longitude]" value="<?php h(_d($data,'longitude'))?>""><br> <input type="checkbox" name="deg60" value="1" id="deg60" onclick="display_latlng()" > <label for="deg60">60進(緯度:ddmmss.ss 経度:dddmmss.ss)で入力</label><br>10進・60進の切り替えを実現するために、入力用のtextフィールドのほかにhiddenフィールド、切り替え指示用のcheckboxを用意する。
function display_latlng(){ if(document.getElementById('deg60').checked){ document.getElementsByName('latitude')[0].value = dec_to_60(document.getElementsByName('data[latitude]')[0].value,2); document.getElementsByName('longitude')[0].value = dec_to_60(document.getElementsByName('data[longitude]')[0].value,3); }else{ document.getElementsByName('latitude')[0].value = document.getElementsByName('data[latitude]')[0].value; document.getElementsByName('longitude')[0].value = document.getElementsByName('data[longitude]')[0].value; } } function dec_to_60(deg,w){ var ji = Math.floor(deg); var hun = Math.floor((deg-ji)*60); var byou = ((deg-ji)*60-hun)*60; var byou_n = Math.floor(byou); var byou_z = Math.floor((byou-byou_n)*100); ji = ('000'+ji).substr(-w); hun = ('00'+hun).substr(-2); byou = ('00'+byou_n).substr(-2)+'.'+('00'+byou_z).substr(-2); return ji+hun+byou; } function dec_from_60(n,w){ n = ''+n; var ji = parseInt(n.substr(0,w)); var hun = parseInt(n.substr(w,2)); var byou = parseFloat(n.substr(w+2,5)); if(isNaN(ji)||isNaN(hun)||isNaN(byou)||hun>60||hun<0||byou>60||byou<0){ return false; } return ji+hun/60+byou/3600; }緯度・経度の60進表記を10新表記に変換する関数dec_from_60および10進表記を60進表記に変換する関数dec_to_60を用意する。 なお、緯度と経度で桁数が異なる(緯度はddmmss.ss、経度はdddmmss.ss)ので、第2引数で2桁か3桁かを選択できるようにする。 display_latlngは、hiddenフィールドに入力された数値をtextフィールドに表示する関数であり、ページが読み込まれた時や地図や端末の現在地を入力した時に実行する。
display_latlng(); document.getElementsByName('latitude')[0].onchange = function(){ var latitude; if(document.getElementById('deg60').checked){ latitude = dec_from_60(this.value,2); if(!latitude)latitude = ''; }else{ latitude = this.value; } document.getElementsByName('data[latitude]')[0].value=latitude; } document.getElementsByName('longitude')[0].onchange = function(){ var longitude; if(document.getElementById('deg60').checked){ longitude = dec_from_60(this.value,3); if(!longitude)longitude = ''; }else{ longitude = this.value; } document.getElementsByName('data[longitude]')[0].value=longitude; }ページ読み込み時の初期化関数(今回の例ではinit())に、textフィールドに値が入力された場合の処理を記載する。
<input type="hidden" name="data[horizontal_accuracy]" value="<?php h(_d($data,'horizontal_accuracy'))?>""> 測定精度: 絶対精度: <select id="horizontal_absolute_accyracy" onchange="absolute_accyracy_change('horizontal');"> <option value='0</option> <option value='10高精度</option> <option value='20中精度</option><option value='30低精度</option> <option value='99精度不明</option> </select> 相対精度: <select id="horizontal_relative_accuracy" onchange="relative_accuracy_change('horizontal');"></select><br>精度を保持するhiddenフィールドと、絶対精度・相対精度を選択するselectを用意する。 hiddenフィールドには、data[*_accuracy]というname、各selectにはidとして*_relative_accuracy、*_absolute_accyracyをidを設定する。 絶対精度には、選択肢をoptionタグによりあらかじめ用意し、相対精度は絶対制度に応じて選択肢を変化させるため、空のselectを用意する。
function absolute_accyracy_change(direction){ var sel_ra = document.getElementById(direction+'_relative_accuracy'); var val_ra = sel_ra.value; var sel_aa = document.getElementById(direction+'_absolute_accyracy'); var val_aa = sel_aa.value; sel_ra.innerHTML = ''; if(val_ra == '')val_ra = '0'; if(val_aa == 99 || val_aa == 0){ sel_ra.setAttribute('disabled','disabled'); document.getElementsByName('data['+direction+'_accuracy]')[0].value = val_aa == 99? 99 : ''; }else{ sel_ra.removeAttribute('disabled','disabled'); ['','特に高精度','高精度','中精度','低精度'].map(function(str,i){ if(direction == 'altitude' && i == 3) return; if(i>(val_aa/10+1)) return; var opt = document.createElement('option'); opt.innerText = str; opt.value = i; if(val_ra == i)opt.selected = true; sel_ra.appendChild(opt); }); document.getElementsByName('data['+direction+'_accuracy]')[0].value = parseInt(val_ra)+parseInt(val_aa); } } function accuracy_change(direction){ var accuracy = document.getElementsByName('data['+direction+'_accuracy]')[0]; var absolute_accyracy = document.getElementById(direction+'_absolute_accyracy'); var value = accuracy.value if(accuracy.value == 99) absolute_accyracy.value = 99; else if(accuracy.value > 0) absolute_accyracy.value = Math.floor(accuracy.value/10)*10; else accuracy.value = 0; absolute_accyracy_change(direction); document.getElementById(direction+'_relative_accuracy').value = value - absolute_accyracy.value; accuracy.value = value; } function relative_accuracy_change(direction){ document.getElementsByName('data['+direction+'_accuracy]')[0].value = parseInt(document.getElementById(direction+'_absolute_accyracy').value) + parseInt(document.getElementById(direction+'_relative_accuracy').value); }hiddenフィールドがほかの部分のJavaScriptから変更された場合やページ読み込み時に実行される
accuracy_change()
、絶対精度のselectが変更されたときに呼び出されるabsolute_accyracy_change()
、相対精度のselectが変更されたときに呼び出されるrelative_accuracy_change()
の3つの関数を用意する。
引数directionは、文字列'horizontal'はたは'altitude'のいずれかである。
accuracy_change(direction)
が呼び出されると、hiddenフィールドから値を読み出し、変数に入れておく。次に
10の位を絶対精度のselectにセットし、absolute_accyracy_change(direction)
を呼び出す。
すると相対精度のselectに選択肢が用意されるので、その後にhiddenフィールドの値の1の位を相対精度の値としてセットする。
この過程でhiddenフィールドの値が破壊される場合があるので、最初に読みだしておいた値を書き戻す。
absolute_accyracy_change(direction)
が呼び出されると、絶対精度の値をもとに相対精度の選択肢を変化させる。
相対精度は、絶対精度が高精度の場合は「特に高精度」「高精度」、中精度の場合には「特に高精度」「高精度」「中精度」など選択肢が変化する。
また、絶対精度が空白の場合は精度不明の場合には相対精度は選択させない。
このように場合分け及び値の演算(相対精度は絶対精度の値/10+1より大きい)により選択肢を決定し、それを相対精度の欄にセットする。
最後にhiddenフィールドに新たに選択された絶対精度および相対精度の値から求めた値をセットする。
relative_accyracy_change(direction)
が呼び出されると、hiddenフィールドに選択された絶対精度および相対精度の値から求めた値をセットする。
<dt class=" pubtag <?php echo in_array('name',$error_params)?'error':''?>""><input type="checkbox" class="modify" >名称</dt> <dd><input type="text" name="data[name]" value="<?php h(_d($data,'name'))?>""></dd>チェックボックスは、登録申請時の入力画面では、次のCSSを出力することにより非表示とされている。
input.modify{ display: none; }また、修正申請時の入力画面では、次のJavaScriptが出力され、チェックボックスによる操作が有効化されている。
function init(){ var modify = document.getElementsByClassName('modify'); for(var i=0; i<modify.length; i++){ modify[i].onclick = toggle_modify; toggle_modify2(modify[i]); } } function toggle_modify(){ toggle_modify2(this); } function toggle_modify2(element){ var tagnames = ['input','select','textarea']; for(var j=0; j<tagnames.length; j++){ var ii = element.parentNode.nextSibling.nextSibling.getElementsByTagName(tagnames[j]); for(var i=0; i<ii.length; i++){ if(element.checked){ ii[i].removeAttribute('disabled','disabled'); }else{ ii[i].setAttribute('disabled','disabled'); } } } }
init()
はページ読み込み時に実行されるよう設定された関数であり、この中で各チェックボックスが操作された際のイベントハンドラtoggle_modify
を設定するとともに、チェックされているか否かに応じて入力欄を有効化・無効化する関数toggle_modify2()
を呼び出す。
toggle_modify()
は操作されたcheckboxを引数としてtoggle_modify2()
を呼び出している。
toggle_modify2(element)
は、引数elementで与えられたチェックボックスに対して処理を行う。
チェックボックス'element'を囲っているdlは、element.parentNode
である。また、それに続くddは、element.parentNode.nextSibling.nextSibling
である。
その中から指定するタグをリストアップするには、例えばinputタグであればelement.parentNode.nextSibling.nextSibling.getElementsByTagName('input')
とする。
このようにしてリストアップされたすべての入力欄(input、select、textarea)に対して、'element'のチェックが外れた状態であれば、属性disableを設定する。
すると、入力や値の選択が不可となるほかに、フォームの情報をサーバーに送信する際に、送信する対象外となる。'element'のチェックがされた状態であれば、属性disableを取り去る。
<input type="hidden" name="data[level_code]" value=""> <select name="kaiso" > <option value="" ></option> <option value="0" >屋内</option> <option value="999" >屋外</option> <option value="998" >屋上</option> <option value="997" >海底、湖底、川底</option> </select><br> <div id="okunai"> 階数: <select name="kaisuu" > <option value="200" >200階</option> ...略... <option value="1">1階</option> ...略... <option value="-50">地下50階</option> </select> <select name="data[middle_floor]" > <option value="0" >整数階</option><option value="0.5" >中間階</option> </select> </div>この部分のPHPコードを示すと下記のようになる。ただし、
make_select()
はselectを容易に出力するために作成した関数である。
<input type="hidden" name="data[level_code]" value="<?php h(_d($data,'level_code'))?>""> <?php echo make_select('kaiso',$kaiso_list,!isset($data['level_code'])||$data['level_code']==''?'':($data['level_code']<989?'0':$data['level_code'])) ?><br> <div id="okunai"> 階数: <?php echo make_select('kaisuu',get_kaisuu_list(),isset($data['level_code'])&&$data['level_code']<989?$data['level_code']:1); ?> <?php echo make_select('data[middle_floor]',array('0'=>'整数階','0.5'=>'中間階'),_d($data,'middle_floor')) ?> </div>また、JavaScriptは次のようになる。ただし、
init()
はページ読み込み時に自動実行されるよう設定された関数である。
function init(){ toggle_okunai(); document.getElementsByName('kaiso')[0].onchange = function(){ toggle_okunai(); if(this.value=='0'){ document.getElementsByName('data[level_code]')[0].value = document.getElementsByName('kaisuu')[0].value; }else{ document.getElementsByName('data[level_code]')[0].value = this.value; document.getElementsByName('data[middle_floor]')[0].value = 0; } } document.getElementsByName('kaisuu')[0].onchange = function(){ document.getElementsByName('data[level_code]')[0].value = this.value; } } function toggle_okunai(){ if(document.getElementsByName('kaiso')[0].value=='0'){ document.getElementById('okunai').style.display = 'block'; }else{ document.getElementById('okunai').style.display = 'none'; } }
document.getElementsByName('kaiso')[0].onchange
はkaisoが変更された際に実行される処理を設定している。
document.getElementsByName('kaisuu')[0].onchange
はkaisuuが変更された際の処理を設定する。
toggle_okunai
はkaisoが変更された際、およびinit()
から呼び出される関数だが、kaisoの値が0の場合には階数の入力欄を表示し、それ以外の場合には非表示としている。
<dl id="required"> 略 </dl> <dl id="optional"> 略 </dl>これに対し、次のCSSを適用することで、ページ読み込み時には必須項目のみを表示させる。
dl#optional{ display: none; }また、必須項目と任意項目の表示を切り替えるには、次のJavaScript関数を用意し、切り替えボタンが押されたときに実行されるようにする。
function toggle_required_optional(){ var required = document.getElementById('required'); var optional = document.getElementById('optional'); var btn = document.getElementById('btn_toggle_required_optional'); if(required.style.display == 'none'){ required.style.display = 'block'; optional.style.display = 'none'; btn.value = '任意項目入力'; }else{ required.style.display = 'none'; optional.style.display = 'block'; btn.value = '必須項目入力'; } }