こんちわ。松田です。
最近作っているシステムで、以下のようなお題が出されました。
問:セレクトボックスで選択した要素を↑↓ボタンで並び替えよ。ただし、CTRL選択による複数選択にも対応すること。(10点)
JavaScriptのライブラリは腐るほど出回っているのでとりあえずググろうかと思いましたが、そもそもなんてキーワードで検索したらいいのか分かりません。
「セレクトボックス 並び替え」「selectbox 要素 移動」「selectbox move」・・・ うーん。。。
日本語で検索して引っかからないと、英語ページに救いを求め、だんだんとシンプルな英単語でググっていくこと になりますが、今回はなかなかいい結果が見つかりません。
そんなわけでこれは自分で実装してみることにしました。
まずは↓ボタンから作るか。ということで、クリックしたら呼び出される関数をとりあえず定義。
そして、<option>タグの要素を取ってくるところまでを作成。
<a href='javascript:;void(0);' onclick='moveDownElement()'>↓</a>
<script type="text/javascript">
function moveDownElement() {
var selectbox = document.getElementById('selectbox_id');
var option_list = selectbox.getElementsByTagName('option');
}
</script>
次に各optionを移動させるための方法を考える。
removeChild()して指定したoptionを取り出して、一つ下のoptionにappendChild()すればいいん じゃないかなーと、なんとなーく思いついたけどうまくいかない。
そっか。appendChild()だと指定した要素に子の要素として追加しちゃうから、これじゃだめなのか。
子じゃなく兄弟の位置に要素を追加するのはなんて関数だっけ・・・。なんかあったような・・・。
うーん。関数名見ればたぶん一発でわかるんだけど。
どうしても思い浮かばないので奥の手を使おう。
秘技・要素全部出し!
<script type="text/javascript">
var element = document.createElement('div');
for (var i in element) {
document.write(element[i]);
}
</script>
お?insertBefore()ってのがある。なんかこれっぽい!
早速これを使って実装再開。
selected指定が付いているoptionをremoveChild()してinsertBefore()で挿入する。と・・・
<script type="text/javascript">
function moveDownElement() {
var selectbox = document.getElementById('selectbox_id');
var option_list = selectbox.getElementsByTagName('option');
for (var i = 0; i < option_list.length; i++) {
if (option_list[i].selected) {
selectbox.insertBefore(selectbox.removeChild(option_list[i]), option_list[i+1]);
}
}
}
</script>
動いた!
けどなんか変!
そうか。[i]と[i+1]を上から順に入れ替えていくから一番上の要素が一気に下に行っちゃうのね。
よく考えたら当たり前か。やる前に気付け!
よーし、じゃあfor文を逆順にしちゃえ。
<script type="text/javascript">
function moveDownElement() {
var selectbox = document.getElementById('selectbox_id');
var option_list = selectbox.getElementsByTagName('option');
for (var i = option_list.length-1; i >= 0; i--) {
if (option_list[i].selected) {
selectbox.insertBefore(selectbox.removeChild(option_list[i]), option_list[i+1]);
}
}
}
</script>
できた!
けどまだ動きがちょっとおかしい。
optionを一つだけ動かすときはいいんだけど、複数個選択して一番下まで持ってくると、要素がくるくる入れ替わっちゃう。
なるほど。入れ替え先のoptionが一番下の要素の場合は入れ替えちゃダメなのか。
ついでに入れ替え先がselectedの場合もはじくようにしておこう。
あとはこれの↑ボタンバージョンも作って完成!
<script type="text/javascript">
function moveUpElement() {
var selectbox = document.getElementById('selectbox_id');
var option_list = selectbox.getElementsByTagName('option');
for (var i = 0; i < option_list.length; i++) {
if (option_list[i].selected) {
if (i > 0 & & !option_list[i-1].selected) {
selectbox.insertBefore(selectbox.removeChild(option_list[i]), option_list[i-1]);
}
}
}
}
function moveDownElement() {
var selectbox = document.getElementById('selectbox_id');
var option_list = selectbox.getElementsByTagName('option');
for (var i = option_list.length-1; i >= 0; i--) {
if (option_list[i].selected) {
if (i < option_list.length-1 & & !option_list[i+1].selected) {
selectbox.insertBefore(selectbox.removeChild(option_list[i]), option_list[i+1]);
}
}
}
}
</script>