javascriptの質問です

selectで回数の範囲を選び、その選んだ行をシャッフルして表示するというプログラムを作りたいと思っています。
どうすればjavascriptで回数を回数を選んで表示できるでしょうか?

<html><head><script>
function sortTable(){
var tabs = document.getElementsByTagName('TABLE');
var tab = tabs[0];
var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
for (var r = bodies.length; r > 0; r--) {
var index = Math.floor(r * Math.random());tab.appendChild(bodies[index]);
bodies.splice(index, 1);}}</script></head>
<body>回数範囲選択
<select name="kaisu1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>~
<select name="kaisu2">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="button" value="をシャッフル表示" onclick="sortTable()">
<table>
<tr><td>回数</td><td></td></tr>
<tr><td>1</td><td>a</td></tr>
<tr><td>2</td><td>b</td></tr>
<tr><td>3</td><td>c</td></tr>
<tr><td>4</td><td>d</td></tr>
</table></body></html>

よろしくお願いします。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/09/08 14:17:11
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:a-kuma3 No.2

回答回数4973ベストアンサー獲得回数2154

ポイント249pt

こんな感じでどうでしょう。

<html><head><script>
function getKaisu(id) {
    var sel = document.getElementById(id);
    var index = sel.selectedIndex;
    return parseInt(sel.options[index].value);
}
function sortTable(){
    var kaisu1 = getKaisu("kaisu1");
    var kaisu2 = getKaisu("kaisu2");

    // シャッフルする意味が無い
    if (kaisu1 == kaisu2) {
        return;
    }
    // kaisu1 が小さくなるようにする
    if (kaisu1 > kaisu2) {
        var n = kaisu2;
        kaisu2 = kaisu1;
        kaisu1 = n;
    }
    var tabs = document.getElementsByTagName('TABLE');
    var tab = tabs[0];
    for (var i = 0 ; i < 100 ; ++i) {
        var index = kaisu1 + Math.floor((kaisu2 - kaisu1 + 1) * Math.random());
        var trs = document.getElementsByTagName('tr');
        var tr = trs[index];
        tr.parentNode.insertBefore(tr, trs[kaisu1]);
    }
}
</script>
</head>
<body>回数範囲選択
<select id="kaisu1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>~
<select id="kaisu2">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="button" value="をシャッフル表示" onclick="sortTable()">
<table>
<tr><td>回数</td><td></td></tr>
<tr><td>1</td><td>a</td></tr>
<tr><td>2</td><td>b</td></tr>
<tr><td>3</td><td>c</td></tr>
<tr><td>4</td><td>d</td></tr>
</table></body></html>

スクリプトの部分に、それなりに手を入れました。
HTML の部分は、<select> の name 属性を、id 属性に変えてます。
回数1と回数2の大きさは、どちらが大きくても動作するようにしてます。


jsFiddle で試したのが、こちらです。
http://jsfiddle.net/a_kuma3/Q9BMX/

動作が分かりやすいように、回答で書いたコードと以下の点が違っています。

  • 選択肢の数を9に増やしました
  • シャッフルで移動した行の背景に色を付けました








質問の意図を取り違えていましたので、あらためての回答です。
回数範囲に関係なく、全シャッフルした後に、回数範囲以外の行を display: none しています。

<html><head><script>
function sortTable(){
    var tabs = document.getElementsByTagName('TABLE');
    var tab = tabs[0];
    var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
    for (var r = bodies.length; r > 0; r--) {
        var index = Math.floor((r - 1) * Math.random()) + 1;    // こうしないと、先頭行も対象になってしまいます
        tab.appendChild(bodies[index]);
//      bodies.splice(index, 1);        この処理は必要ないです
    }
    /* ここまでは、ほとんど同じです */


    var kaisu1 = document.getElementsByName('kaisu1')[0].value;
    var kaisu2 = document.getElementsByName('kaisu2')[0].value;
    if (kaisu1 > kaisu2) {
        var n = kaisu2;
        kaisu2 = kaisu1;
        kaisu1 = n;
    }
    var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
    for (var i = 1 ; i < bodies.length ; ++i) {
        var kaisu = parseInt(bodies[i].firstChild.innerHTML);
        if (kaisu < kaisu1 || kaisu2 < kaisu) {
            bodies[i].style.display = "none";
        }
    }

}</script></head>
<body>回数範囲選択
<select name="kaisu1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>~
<select name="kaisu2">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="button" value="をシャッフル表示" onclick="sortTable()">
<table>
<tr><td>回数</td><td></td></tr>
<tr><td>1</td><td>a</td></tr>
<tr><td>2</td><td>b</td></tr>
<tr><td>3</td><td>c</td></tr>
<tr><td>4</td><td>d</td></tr>
</table></body></html>

質問のままのコードだと、先頭行までシャッフルの対象になってしまうので、少しだけ変更しています。

jsFiddle で確認したのが、こちらになります。
http://jsfiddle.net/a_kuma3/sWNdx/

他4件のコメントを見る
id:takanii

ありがとうございます。
今ソースを見ましたところ

<tr>
<td>1</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>2</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>3</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>4</td>
<td>hoge</td>
<td>hoge</td>
</tr>

というように改行されておりました
各trの中の一番最初のtdの値を取得してくるにはどのようにすればいいのでしょうか?
度々すみません

2013/09/08 13:04:25
id:a-kuma3

各trの中の一番最初のtdの値を取得してくるにはどのようにすればいいのでしょうか?

おっと。
書き直したコードの以下の行を、

        var kaisu = parseInt(bodies[i].firstChild.innerHTML);

このように変更してください。

        var kaisu = parseInt(bodies[i].cells[0].innerHTML);

firstChild → cells[0] です。

2013/09/08 13:49:57

その他の回答1件)

id:Lhankor_Mhy No.1

回答回数814ベストアンサー獲得回数232

ポイント51pt

もともとのコードからは大分変わってしまいますが。

function sortTable(){
    var kaisu1 = document.getElementsByName('kaisu1')[0].value;
    var kaisu2 = document.getElementsByName('kaisu2')[0].value;
    var kaisuLength = Math.abs(kaisu1 - kaisu2)+1;
    var kaisuMin = Math.min(kaisu1, kaisu2);
    var tabs = document.getElementsByTagName('TABLE');
    var tab = tabs[0];
    var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
    var keyArr = new Array(bodies.length);
    
    for (var i = 0; i < keyArr.length; i++) keyArr[i] = i;
    for (var i = 0; i < 100; i++) {
        var swap1 = Math.floor(kaisuLength * Math.random() + kaisuMin);
        var swap2 = Math.floor(kaisuLength * Math.random() + kaisuMin);
        keyArr[swap1] = [keyArr[swap2], keyArr[swap2] = keyArr[swap1]][0];
    }
    for (var i = 0; i < bodies.length; i++) tab.appendChild(bodies[keyArr[i]]);
}
id:a-kuma3
document.getElementsByName('kaisu1')[0].value

おっと、これで取れるんだ :-O

2013/09/08 11:50:49
id:a-kuma3 No.2

回答回数4973ベストアンサー獲得回数2154ここでベストアンサー

ポイント249pt

こんな感じでどうでしょう。

<html><head><script>
function getKaisu(id) {
    var sel = document.getElementById(id);
    var index = sel.selectedIndex;
    return parseInt(sel.options[index].value);
}
function sortTable(){
    var kaisu1 = getKaisu("kaisu1");
    var kaisu2 = getKaisu("kaisu2");

    // シャッフルする意味が無い
    if (kaisu1 == kaisu2) {
        return;
    }
    // kaisu1 が小さくなるようにする
    if (kaisu1 > kaisu2) {
        var n = kaisu2;
        kaisu2 = kaisu1;
        kaisu1 = n;
    }
    var tabs = document.getElementsByTagName('TABLE');
    var tab = tabs[0];
    for (var i = 0 ; i < 100 ; ++i) {
        var index = kaisu1 + Math.floor((kaisu2 - kaisu1 + 1) * Math.random());
        var trs = document.getElementsByTagName('tr');
        var tr = trs[index];
        tr.parentNode.insertBefore(tr, trs[kaisu1]);
    }
}
</script>
</head>
<body>回数範囲選択
<select id="kaisu1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>~
<select id="kaisu2">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="button" value="をシャッフル表示" onclick="sortTable()">
<table>
<tr><td>回数</td><td></td></tr>
<tr><td>1</td><td>a</td></tr>
<tr><td>2</td><td>b</td></tr>
<tr><td>3</td><td>c</td></tr>
<tr><td>4</td><td>d</td></tr>
</table></body></html>

スクリプトの部分に、それなりに手を入れました。
HTML の部分は、<select> の name 属性を、id 属性に変えてます。
回数1と回数2の大きさは、どちらが大きくても動作するようにしてます。


jsFiddle で試したのが、こちらです。
http://jsfiddle.net/a_kuma3/Q9BMX/

動作が分かりやすいように、回答で書いたコードと以下の点が違っています。

  • 選択肢の数を9に増やしました
  • シャッフルで移動した行の背景に色を付けました








質問の意図を取り違えていましたので、あらためての回答です。
回数範囲に関係なく、全シャッフルした後に、回数範囲以外の行を display: none しています。

<html><head><script>
function sortTable(){
    var tabs = document.getElementsByTagName('TABLE');
    var tab = tabs[0];
    var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
    for (var r = bodies.length; r > 0; r--) {
        var index = Math.floor((r - 1) * Math.random()) + 1;    // こうしないと、先頭行も対象になってしまいます
        tab.appendChild(bodies[index]);
//      bodies.splice(index, 1);        この処理は必要ないです
    }
    /* ここまでは、ほとんど同じです */


    var kaisu1 = document.getElementsByName('kaisu1')[0].value;
    var kaisu2 = document.getElementsByName('kaisu2')[0].value;
    if (kaisu1 > kaisu2) {
        var n = kaisu2;
        kaisu2 = kaisu1;
        kaisu1 = n;
    }
    var bodies = Array.prototype.slice.apply(tab.getElementsByTagName('tr'));
    for (var i = 1 ; i < bodies.length ; ++i) {
        var kaisu = parseInt(bodies[i].firstChild.innerHTML);
        if (kaisu < kaisu1 || kaisu2 < kaisu) {
            bodies[i].style.display = "none";
        }
    }

}</script></head>
<body>回数範囲選択
<select name="kaisu1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>~
<select name="kaisu2">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="button" value="をシャッフル表示" onclick="sortTable()">
<table>
<tr><td>回数</td><td></td></tr>
<tr><td>1</td><td>a</td></tr>
<tr><td>2</td><td>b</td></tr>
<tr><td>3</td><td>c</td></tr>
<tr><td>4</td><td>d</td></tr>
</table></body></html>

質問のままのコードだと、先頭行までシャッフルの対象になってしまうので、少しだけ変更しています。

jsFiddle で確認したのが、こちらになります。
http://jsfiddle.net/a_kuma3/sWNdx/

他4件のコメントを見る
id:takanii

ありがとうございます。
今ソースを見ましたところ

<tr>
<td>1</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>2</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>3</td>
<td>hoge</td>
<td>hoge</td>
</tr>
<tr>
<td>4</td>
<td>hoge</td>
<td>hoge</td>
</tr>

というように改行されておりました
各trの中の一番最初のtdの値を取得してくるにはどのようにすればいいのでしょうか?
度々すみません

2013/09/08 13:04:25
id:a-kuma3

各trの中の一番最初のtdの値を取得してくるにはどのようにすればいいのでしょうか?

おっと。
書き直したコードの以下の行を、

        var kaisu = parseInt(bodies[i].firstChild.innerHTML);

このように変更してください。

        var kaisu = parseInt(bodies[i].cells[0].innerHTML);

firstChild → cells[0] です。

2013/09/08 13:49:57
id:takanii

選択範囲の回数をtableの一行目から探索して

例えば 以下のテーブルで回数選択を1-2にしてシャッフルした場合

1 a

2 b

2 c

3 b

1行目から3行目までをシャッフルして表示し

範囲選択外のテーブルはdisplay:none;して欲しいのですが

どのように書けばいいでしょうか?

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません