28740
以下のソースコードで、`<tbody id=”p2146-2-tbody”> ～
</tbody>`の範囲を「追加」、「削除」、「移動」、「変更」させたいのですが、どのようにすべきでしょうか？  
現在、上手く動かせず、アドバイス頂けましたら幸いです。  
何卒宜しくお願い致します。

【index.html】

```

    <table id="p2146-2-table">
    <tbody id="p2146-2-tbody">
    <tr>
      <th>仕入れ先A</th>
      <th>仕入れ先B</th>
      <th>仕入れ先C</th>
    </tr>
    
    <tr>
      <td>
        <select class="changeList">
          <option>A</option><option>B</option><option>C</option>
        </select>
      </td>
      <td>A</td>
      <td>
        <img src="up.png" alt="↑" class="upList" />上へ　
        <img src="down.png" alt="↓" class="downList" />下へ
      </td>
    </tr>
    
    <tr>
      <th>販売先A</th>
      <th>販売先B</th>
      <th>販売先C</th>
    </tr>
    
    <tr>
      <td>
        <select class="changeList">
          <option>A</option><option>B</option><option>C</option>
        </select>
      </td>
      <td>A</td>
      <td>
        <img src="up.png" alt="↑" class="upList" />上へ　
        <img src="down.png" alt="↓" class="downList" />下へ
      </td>
    </tr>
    
    <tr class="text-center">
    <td>
      <input value="+" type="button" class="addList">　
      <input value="-" type="button" class="removeList">
    </td>
    </tr>
    </tbody>
    </table>
    
```

【style.css】

```

    #p2146-2-tbody tr:first-child {
      display: none;
    }
    
```

【jQuery.js】

```

    $(document).ready(function () {
    
      // CSSで非表示にした1行目の行を複製し、その行の下に挿入
      $("#p2146-2-tbody > tr").eq(0).clone(true).insertAfter($("#p2146-2-tbody > tr")).eq(0);
    
      // 行を追加する
      $(document).on("click", ".addList", function () {
        $("#p2146-2-tbody > tr").eq(0).clone(true).insertAfter(
          $(this).parent().parent()
       );
      });
    
      // 行を削除する
      $(document).on("click", ".removeList", function () {
        $(this).parent().parent().remove();
      });
    
      // 行を一つ上に移動させる
      $(document).on("click", "#p2146-2-tbody > tr:gt(1) .upList", function () {
        var t = $(this).parent().parent();
        if(t.prev("tr")) {
          t.insertBefore(t.prev("tr")[0]);
        }
      });
    
      // 行を一つ下に移動させる
      $(document).on("click", ".downList", function () {
        var t = $(this).parent().parent();
        if(t.next("tr")) {
          t.insertAfter(t.next("tr")[0]);
        }
      });
    
      // 行の一部を変更する
      $(document).on("change", ".changeList", function () {
        $(this).parent().next().html($(this).val());
      });
    
    });
    
```

### ※追記

`<tbody id=”p2146-2-tbody”> ～ </tbody>`の中の、以下全てを「追加」「削除」「移動」「変更」したいです。

```

    <tr>
      <th>仕入れ先A</th>
      <th>仕入れ先B</th>
      <th>仕入れ先C</th>
    </tr>
    
    <tr>
      <td>
        <select class="changeList">
          <option>A</option><option>B</option><option>C</option>
        </select>
      </td>
      <td>A</td>
      <td>
        <img src="up.png" alt="↑" class="upList" />上へ
        <img src="down.png" alt="↓" class="downList" />下へ
      </td>
    </tr>
    
    <tr>
      <th>販売先A</th>
      <th>販売先B</th>
      <th>販売先C</th>
    </tr>
    
    <tr>
      <td>
        <select class="changeList">
          <option>A</option><option>B</option><option>C</option>
        </select>
      </td>
      <td>A</td>
      <td>
        <img src="up.png" alt="↑" class="upList" />上へ　
        <img src="down.png" alt="↓" class="downList" />下へ
      </td>
    </tr>
    
    <tr class="text-center">
      <td>
        <input value="+" type="button" class="addList">
        <input value="-" type="button" class="removeList">
      </td>
    </tr>
    
```
CC BY-SA 3.0
2016-09-07T05:54:10.333
28736
2016-09-08T11:47:32.507
2016-09-08T04:09:18.110
12323
question
javascript html jquery
JavaScript / jQueryでtableの行を「追加」「削除」「移動」「変更」する方法を教えてください。
回答させていただきます。スニペットを作ってみました。ご確認下さい。

**コメント**

  1. 下記行にて行っているコピーが見出し行のコピーになっています 

>
```>     // CSSで非表示にした1行目の行を複製し、その行の下に挿入

>     $("#p2146-2-tbody > tr").eq(0).clone(true).insertAfter($("#p2146-2-tbody
> > tr")).eq(0);
>  
```

こちらは以下のように見出し行と明細行を分けたほうが処理し易いです。

```

    <thead>
      <!-- 見出し行 -->
      <tr>
        <th>販売先A</th>
        <th>販売先B</th>
        <th>販売先C</th>
      </tr>
    </thead>
    <tbody>
      <!-- 明細行 -->
      <tr>
      ...
      </tr>
    </tbody>
    
```

  2. `addList`と`removeList`のボタンが`table`の中に入っていますが外に出しました。  
特に理由がなければ、外に出したほうが処理が行い易いと思います。

  3. `parent()`を使ってタグを追っていくよりも、`closest()`を使用して特定のタグを指定するほうが見やすいですし、タグ階層の変更の場合に`parent().parent()`よりは少しだけ楽になれるかもしれません。

**注記**

  * ご質問時のコードでは`table`が2つありますが、勝手ながらスニペットの見やすさのために1つにしました。

```

        $(function(){
      $("#table2 tbody tr").eq(0).clone(true).insertAfter($("#table2 tbody tr")).eq(0);
    
      // 行を一つ上に移動させる
      $(document).on("click", ".upList", function () {
        var $tr = $(this).closest("tr");
        if($tr.prev("tr")) {
          $tr.insertBefore($tr.prev("tr").not(":hidden")[0]);
        }
      });
    
      // 行を一つ下に移動させる
      $(document).on("click", ".downList", function () {
        var $tr = $(this).closest("tr");
        if($tr.next("tr")) {
          $tr.insertAfter($tr.next('tr').not(":hidden")[0]);
        }
      });
    
      // 行を追加する
      $(document).on("click", ".addList", function(){
        // tableの1行目に隠しているhidden行を使用してtr:lastに追加
        var $newRow = $("#table2 tbody tr:hidden").clone();
        // デフォルト値設定等(必要であれば)
        $newRow.find("changeList").prop('selectedIndex', 0);
        $newRow.insertAfter($("#table2 tbody tr:last"));
      });
    
      // 行を削除する
      $(document).on('click', '.removeList', function() {
        $('#table2 tbody tr:last').not(":hidden").remove();
      });
    
      // 行の一部を変更する
      $(document).on("change", ".changeList", function () {
        $(this).closest("td").next("td").text($(this).val());
      });
    });
```

```

        #table2 tbody tr:first-child {
          display: none;
        }
```

```

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <table id="table2">
      <thead>
        <tr>
          <th>販売先A</th>
          <th>販売先B</th>
          <th>販売先C</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>
            <select class="changeList">
              <option>A</option><option>B</option><option>C</option>
            </select>
          </td>
          <td>A</td>
          <td>
            <img src="up.png" alt="↑" class="upList" />上へ　
            <img src="down.png" alt="↓" class="downList" />下へ
          </td>
        </tr>
      </tbody>
    </table>
    
    <input value="+" type="button" class="addList">　
    <input value="-" type="button" class="removeList">
```

* * *

**回答追記**

すみませんこちらこそなかなか意図を理解できず(汗  
なんか自信なくなってきましたwさて、これでいいんじゃないでしょうか?

```

      // 追加
      $(document).on("click", ".addList", function(){
        var $newRows = $("table tbody tr:lt(4)").clone();
        var index = $(this).closest("tr").index();
        $newRows.insertBefore($("table tbody tr:last"));
      });
    
      // 削除
      $(document).on('click', '.removeList', function() {
        var index = $(this).closest("tr").index() - 5;
        if (index >= 0)
          $("table tbody tr:gt(" + index + "):not(.text-center)").remove();
      });
    
```

あと作ってて思ってたんですが、  
並び替えの際に以下の様に仕入先と販売先の何れかが連続する場合があって、

```

    仕入先
    仕入先
    販売店
    販売店
    
```

この状態で追加してしまうと追加される行が

```

    仕入先
    仕入先
    
```

となってしまいますが、それは今のやり方がtrタグを先頭からXXX分コピーしてインサートしているからで、もし上記のような場合を回避したいのであれば、追加処理内でDOMを作成する方が無難かなぁと  
それについては、以下のようなサイトを参考にしてみてください。

[DOM要素の生成](http://qiita.com/kazu56/items/8e92d08fd1bba0a2d771)
CC BY-SA 3.0
2016-09-07T09:00:35.623
28740
2016-09-08T11:47:32.507
2016-09-08T11:47:32.507
12256
12256
28736
answer