SELECT要素の複数連動。その2(iOS Safari(iPad, iPhone, iTouch)で動作可)jQueryなんて使わない。Ajaxも使わない
ちょっと改良した。
- option,optgroup は、htmlで定義した順に表示されるようにした。
- option,optgroup は、混在できる。
- optgroup を指定する value値を拡張できるようにした
- カンマで区切るとoptgroupを複数指定できる。
- * を指定するとすべて表示する
- /^team[ad]$/ig などのように正規表現で利用出きるようにした。(文字によっては文法違反か?)
- selectedの指定は、たぶんマルチにも対応すると思う。前回のclass="selected"は中止。
- 個別のFORMに対応させようとも考えたが、classを同じにしなければ区別で切るのでやめた。
- classは、空白で区切り複数で切るので区別で切るのでSELECTの個別指定もやめた。
- 今後のためにちょっとコメントを書き加えた
それにしてもオブジェクト化するというのは、便利だな。
<!DOCTYPE html> <meta charset="utf-8"> <title>SELECT要素の連動</title> <style> body { color: white; background: black; } </style> <body> <form id="SELECT_TEST"> <p> <label>Group:</label> <select name="group" class="selectA"> <option value="GroupA">GROUP A</option> <option value="GroupB">GROUP B</option> </select> <label>Team:</label> <select name="team" class="selectA"> <optgroup label="GroupA"> <option value="TeamA">TEAM A</option> <option value="TeamB">TEAM B</option> </optgroup> <optgroup label="GroupB"> <option value="TeamC">TEAM C</option> <option value="TeamD">TEAM D</option> </optgroup> </select> <label>Player:</label> <select name="player" class="selectA"> <optgroup label="TeamA"> <option value="PlayerA">PLAYER A</option> <option value="PlayerB">PLAYER B</option> </optgroup> <optgroup label="TeamB"> <option value="PlayerC">PLAYER C</option> <option value="PlayerD">PLAYER D</option> </optgroup> <optgroup label="TeamC"> <option value="PlayerE">PLAYER E</option> <option value="PlayerF">PLAYER F</option> </optgroup> <optgroup label="TeamD"> <option value="PlayerG">PLAYER G</option> <option value="PlayerH">PLAYER H</option> </optgroup> </select> </p> <p> <label>Group:</label> <select name="group" class="selectB"> <option value="GroupA">GROUP A</option> <option value="GroupB" selected>GROUP B</option> <option value="Free">PLAYER Free</option> </select> <label>Team:</label> <select name="team" class="selectB"> <optgroup label="GroupA"> <option value="TeamA">TEAM A</option> <option value="TeamB">TEAM B</option> </optgroup> <optgroup label="GroupB"> <option value="TeamC">TEAM C</option> <option value="TeamD ,TeamC , TeamA" selected>TEAM D</option> </optgroup> <option value="/^f.*$/i">PLAYER Free</option> <option value="/^Team[AD]$/gi">Team A or D</option> <option value="*">Team ALL</option> </select> <label>Player:</label> <select name="player" class="selectB"> <optgroup label="TeamA"> <option value="PlayerA">PLAYER A</option> <option value="PlayerB">PLAYER B</option> </optgroup> <optgroup label="TeamB"> <option value="PlayerC">PLAYER C</option> <option value="PlayerD">PLAYER D</option> </optgroup> <optgroup label="TeamC"> <option value="PlayerE">PLAYER E</option> <option value="PlayerF" selected>PLAYER F</option> </optgroup> <optgroup label="TeamD"> <option value="PlayerG">PLAYER G</option> <option value="PlayerH" selected>PLAYER H</option> <option value="PlayerI" selected>PLAYER I</option> <option value="PlayerJ">PLAYER J</option> </optgroup> <optgroup label="Free"> <option value="Player FreeX">PLAYER FREE X</option> <option value="Player FreeY">PLAYER FREE Y</option> </optgroup> </select> </p> <script> (function (D) { function toAry (nodeList) {//ノードリストを配列 return Array.prototype.slice.call (nodeList); } function getVal (select) {//SELECT値の取得 return select.options[select.selectedIndex].value; } function setSelected (e) {//selectedの設定 e.selected = !! this; } function delChild (e) {//子要素を削除する while (e.hasChildNodes ()) e.removeChild (e.firstChild); } //______ //子要素は、表示用とそのクローンが対になる function ESelect (select) { this.eSelect = select;//b:表示ようにある this.cSelect = select.cloneNode (true);//a:クローン } //親のSELECTのValue値を子のoptgroupのラベルとして検索させ表示する function replaceGroup (label) { var i, e, mode, s; var a = this.cSelect, b = this.eSelect; //a -> b var c = a.childNodes; var ary = [ ], reg, f; switch (true) { case 'string' === typeof label : switch (true) { case (f = /^\/(.+)\/([gmi]*)?$/.exec (label), Array.isArray (f)) : reg = new RegExp (f[1],f[2] || null); mode = 3; break; //正規表現として処理 case /^.+,.+$/.test (label) : ary = label.split (/\s*,\s*/g); mode = 2; break; //配列として処理 case '*' === label : mode = 0; break; default : mode = 1; break; //文字列として処理 } break; default: mode = 0; //すべてコピーする break; } delChild (b);//表示用を削除 for (i = 0; e = c[i]; i += 1) { if ('OPTGROUP' === e.tagName) { switch (mode) { case 1 : if (e.label !== label) continue; break;//文字列として処理 case 2 : if (-1 === ary.indexOf (e.label)) continue; ;break;//配列として処理 case 3 : if (! reg.test (e.label)) continue; break;//正規表現として処理 case 0: default : break;//すべてコピーする } } b.appendChild (e.cloneNode (true));//コピーして表示用のSELECTに追加する } toAry (b.querySelectorAll ('option[selected]')) .forEach (setSelected, true); } //______ //内部での呼び出し(子SELECTをオブジェクト化して呼び出すため) ESelect.prototype.replaceGroup = replaceGroup; //______ //イベント処理 function selectChangeHandle (event) { var e = event.target; var n, t; //親SELECT配列に存在すればvalue値に対応した子のグループを表示させる while (-1 < (n = this.selectBuffer.indexOf (e))) { t = this.cloneBuffer[n]; t.replaceGroup (getVal (e)); e = t.eSelect;//子を親にして孫に対応する } } //SELECT要素に対して初期設定する function init (select) { var buf = { }, begin = [ ]; var i, s, e, n; for (i = 0; s = select[i]; i += 1) { if ((n = s.className)) {//クラスがしていされていたら if (e = buf[n]) { e.addEventListener ('change', this, false);//イベントを貼り付け this.selectBuffer.push (e);//親のSELECT要素を配列に this.cloneBuffer.push (new ESelect (s));//子のSELECT要素を配列にして親と対応する buf[n] = s;//孫に備える } else begin.push (buf[n] = s); //一時保存して2度目の出現に備える } } begin.forEach (function (select) { selectChangeHandle.call (this, { target: select }); }, this); } //______ var Interlock = new Object; Interlock.handleEvent = selectChangeHandle; Interlock.selectBuffer = [ ]; Interlock.cloneBuffer = [ ]; init.call (Interlock, D.querySelectorAll ('select')); }) (document); </script>
(function(l){function m(a){a.selected=!!this}function h(a){this.b=a;this.f=a.cloneNode(!0)}function k(a){a=a.target;for(var b;-1<(b=this.c.indexOf(a));)b=this.a[b],b.g(a.options[a.selectedIndex].value),a=b.b}h.prototype.g=function(a){var b,f,e,c=this.b,n=this.f.childNodes,g=[],d;switch(!0){case "string"===typeof a:switch(!0){case b=/^\/(.+)\/([gmi]*)?$/.exec(a),Array.isArray(b):d=new RegExp(b[1],b[2]||null);e=3;break;case /^.+,.+$/.test(a):g=a.split(/\s*,\s*/g);e=2;break;case "*"===a:e=0;break;default:e= 1}break;default:e=0}for(;c.hasChildNodes();)c.removeChild(c.firstChild);for(b=0;f=n[b];b+=1){if("OPTGROUP"===f.tagName)switch(e){case 1:if(f.label!==a)continue;break;case 2:if(-1===g.indexOf(f.label))continue;break;case 3:if(!d.test(f.label))continue}c.appendChild(f.cloneNode(!0))}Array.prototype.slice.call(c.querySelectorAll("option[selected]")).forEach(m,!0)};var d={};d.handleEvent=k;d.c=[];d.a=[];(function(a){var b={},f=[],e,c,d,g;for(e=0;c=a[e];e+=1)if(g=c.className)(d=b[g])?(d.addEventListener("change", this,!1),this.c.push(d),this.a.push(new h(c)),b[g]=c):f.push(b[g]=c);f.forEach(function(a){k.call(this,{target:a})},this)}).call(d,l.querySelectorAll("select"))})(document);