replaceWithを使う例として、div要素の置換は、よく見かけるけど、select要素の置換はあまり見かけなかったので、メモっとく。
「radioタイプのinput要素(ラジオボタン)を変更した場合に、他のselect要素を選択できなくさせたい」って時に、disabledにするとグレーアウトされて、見た目の変更ができなくて困った。
で考えたのが、readonlyで行こうと。(submitされるけどね)
readonlyなら、フォントの色の変更とかができて自由だし。
でも、select要素には、readonlyがない。
ということで、select要素をtextタイプのinput要素(テキストボックス)に置換して、readonlyにすることで、落ち着いた。
jQueryならシンプルで簡単にできると思ったら、functionの実行時に、DOM操作が即時反映されないことが仇になり、結構苦戦。
素のJavaScriptでやってしまったら負けだと思って、追求したら、なんとかできた。
<!doctype html> <html> <head> <meta charset="utf-8" /> <title>Example</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript"> var example = { /** * idをキーにtextタイプのinput要素に置換したselect要素を保持する連想配列. */ clonedSelects: {} , /** * select要素をtextタイプのinput要素に置換する. * @param id select要素のid * @param value 固定のvalueを指定する(未指定の場合、現在選択中のvalueが設定される) */ replaceToText: function (id, value) { // id内の.(ドット)はエスケープ var elem = $('#' + id.replace(/\./g, '\\.')); // select要素でない場合、処理終了 if (elem[0].nodeName != 'SELECT') { return; } example.clonedSelects[id] = elem.clone(true); // 固定のvalueを設定 if (typeof value !== 'undefined') elem.val(value); // select要素のvalue値をhiddenで持つ var elemHidden = $('<input type="hidden"/>'); // replaceWithを行うまではidが重複するため、別のidにする elemHidden.attr('id', id + 'Hidden'); elemHidden.attr('name', elem.attr('name')); elemHidden.val(elem.val()); elem.after(elemHidden); // select要素をtextタイプのinput要素に置換 elem.replaceWith(function (elem, id) { var elemText = $('<input type="text"/>').attr({readonly: 'readonly', tabindex: '-1'}); elemText.val(elem.children(':selected').text()); elemText.attr('style', elem.attr('style')); // textタイプのinput要素にするため、id,nameを変更 elemText.attr('id', id + 'Text'); elemText.attr('name', elem.attr('name') + 'Text'); return elemText; }(elem, id)); // replaceWithを行った後、select要素のidをhiddenへ設定 elemHidden.attr('id', id); } , /** * textタイプのinput要素をselect要素に戻す. * "戻す"と記載しているのは、select要素を保持しているのが前提のため。 * @param id 戻すselect要素のid * @param value 固定のvalueを指定する(未指定の場合、現在選択中のvalueが設定される) */ replaceToSelect: function (id, value) { // select要素を保持する連想配列に存在しない場合、処理終了 if (typeof example.clonedSelects[id] === 'undefined') { return; } // id内の.(ドット)はエスケープ var elemHidden = $('#' + id.replace(/\./g, '\\.')); // replaceWithを行うとidが重複するため、事前に別のidにする elemHidden.attr('id', id + 'Hidden'); // 固定のvalueを設定 if (typeof value !== 'undefined') elemHidden.val(value); // id内の.(ドット)はエスケープ var elem = $('#' + id.replace(/\./g, '\\.') + 'Text'); elem.replaceWith(function (id, value) { var elemSelect = example.clonedSelects[id]; // select要素に戻すため、idも戻す elemSelect.attr('id', id); elemSelect.val(value); return elemSelect; }(id, elemHidden.val())); // select要素に戻したため、保持していたselect要素を削除 delete example.clonedSelects[id]; // select要素に戻すため、hiddenを削除 elemHidden.remove(); } } </script> </head> <body> <input type="radio" name="radioexample" onclick="example.replaceToSelect('example');" checked="checked" />select要素へ置換 <input type="radio" name="radioexample" onclick="example.replaceToText('example')" />textタイプのinput要素へ置換 <br /> <select id="example" name="example"> <option>サンプル1</option> <option>サンプル2</option> <option>サンプル3</option> </select> </body> </html>
(注)select要素の置換なので、textタイプのinput要素を初期表示としたい場合、onloadでtextタイプのinput要素とすること。
(注)id内のドットのエスケープは、Strutsなどを使用していない限り、なくてもOK。
JavaScriptライブラリを比較するときに、役に立った本。
jQuery、Prototype、Dojo、YUI、script.aculo.usを比較してる。
今は、jQuery優勢かな。
0 件のコメント:
コメントを投稿