テーブルと写真のドラッグ&ドロップによる並べ替え

データや写真を並べ替えたいという時は、時々あるのではないでしょうか。

例えば、ToDoリストで、優先度の高いものを最初に移動させたいというような場合があります。

また、お客さんをスタッフに割り当てる際など、スタッフの順序を入れ替えることができれば、そのまま割り当てに用いることができます。

写真の場合も同様です。例えば、美容院のホームページに記載のヘアースタイルの順番を変えたいという時などです。

このような場合、データベースのファイル名の変更などをしていたら大変手間取りますが、ドラッグ&ドロップで並べ替えができたらとても簡単です。

これには、JQueryのsort機能を使います。

では、テーブル の並べ替えと、写真の並べ替えを順に見ていきましょう。

最初に、両方のデモを見ていただくボタンをここに配置しておきます。

最後の三番目は、この両方を合体させた応用編ですが、後から出てくるデモに入れてあります。

最初に、このデモのコードを載せておきましょう。

テーブル行の並べ替えと、写真(ボックス)の並べ替えの両方が含まれています。

なお、最初にhead内に書いている3つのscript読み込みはJQuery関連ですが、3つ目のtouch-punchというのを付けておくと、スマホでもドラッグ&ドロップができるようになります。

その次のviewportも、PCとスマホの両方に対応する場合は、付けておいた方が良いでしょう。レスポンシブ対応にするためには、通常これを付けます。

<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js'></script>
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<style>
    	.mytable {margin-left: 100px; border-collapse: collapse; width: 250px; border: 1px #333 solid; table-layout: fixed;}
        .mytable th {border: 1px #333 solid; width: 30px;}
        .mytable td {border: 1px #333 solid; width: 220px;}
        .mytbody {cursor: pointer;}
        .mytable {
		   counter-reset: ranking;
		}
        .mytbody th:before {
		   counter-increment: ranking;
		   content: counter(ranking);
		}

        li {float: left; margin: 10px; width: 27%; height: 100px; font-size: 40px; color: red; line-height: 100px; text-align: center; background: #7FB; border: 1px #999 solid; border-radius: 8px; cursor: pointer;}
</style>
</head>
<body>
   <p>DEMO1: テーブル行の並べ替え(ドラッグ&amp;ドロップで並べ替えられます。)</p>
   <table class="mytable">
      <thead>
        <tr>
            <th>No.</th>
            <td>ITEM</td>
        </tr>
      </thead>
      <tbody class="mytbody">
        <tr>
            <th></th>
            <td>買い物に行く</td>
        </tr>
        <tr>
            <th></th>
            <td>○○にメールを書く</td>
        </tr>
        <tr>
            <th></th>
            <td>銀行に行く</td>
        </tr>
        <tr>
            <th></th>
            <td>郵便局に行く</td>
        </tr>
        <tr>
            <th></th>
            <td>洗濯をする</td>
        </tr>
      </tbody>
   </table>

   <p>DEMO2: 写真の並べ替え(ドラッグ&amp;ドロップで並べ替えられます。)</p>

   <div>
	<ul id="photo_sortdata">
		<li>1</li>
		<li>2</li>
		<li>3</li>
		<li>4</li>
		<li>5</li>
		<li>6</li>
		<li>7</li>
          </ul>
	  <div style="clear: both;"></div>
    </div>
</body>
</html>
<script>
$(function(){
    $('.mytbody').sortable();

    $('#photo_sortdata').sortable();
});
</script>

テーブル行の並べ替え

テーブルの方は、まず、5つのToDo項目としてみました。

thタグには番号が入りますが、HTMLでは空欄にしておきます。

tdタグにToDoのアイテムを入れます。

そして、最初のインデックス行より下の部分は、tbodyタグとして、ここが並べ替えの対象になります。

そのため、tbodyにクラス名として何でもいいですが、ここではmytbodyとして、並べ替えを可能にするため、scriptに$(‘.mytbody’).sortable();を書き込みます。

$(function(){ … } はページの読み込みを終えて、DOMの構築が完了した時点に処理をするという構文ですので、付けておいた方が無難かもしれません。

これが基本ですが、テーブルの場合は、自動で番号を付け替えねばなりません。

        .mytable {
		   counter-reset: ranking;
		}
        .mytbody th:before {
		   counter-increment: ranking;
		   content: counter(ranking);
		}

このために、CSSでこのような指定をしています。

これはランクを付けるためのものですが、私はいつもこれをコピーして使っています。

特に並べ替えをしない時などにも、同様の記法が使えますが、私は、並べ替えをしない場合は、わかりやすいように通し番号を書かせるようにしており、並べ替えの時だけ、このようなCSSを使うようにしています。

ご関心のある方は、「counter CSS」などで検索して勉強してみてください。

写真の並べ替え

ここでは簡便のため写真は使わず青緑色のボックスとしましたが、写真でも同様で、liタグの中にimgタグを入れ込むだけです。

リスト方式のタグが使いやすいと思いますが、ここでは、liタグに「float: left」を指定して、画面幅に並ぶことのできる数だけ並んで、いっぱいになると次の行に並ぶというようになります。

ここでは、PCでもスマホでも、3つずつ並ぶように、ボックスの幅を27%に固定しました。

デモを見ていただくとわかりますが、このようにすることで、画像を二次元に配置しても、並べ替えができるようになります。

応用: 番号付き項目の並べ替え

最後の三つ目として、一番目と二番目を合体させたようなタイプを考えてみましょう。

二次元の番号付き項目の並べ替えです。

<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js'></script>
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<style>
        ul {list-style-type: none;}
        li {float: left;}
        table {width: 40vmin; height: 40px; border-collapse: collapse; border: 1px #333 solid; table-layout: fixed;}
        table th {width: 4vmin; border: 1px #333 solid;}
        table td {width: 36vmin; white-space: nowrap; border: 1px #333 solid; font-size: 14px; overflow: hidden;}
        .mylist {
		   counter-reset: ranking;
		}
        .mylist th:before {
		   counter-increment: ranking;
		   content: counter(ranking);
		}
</style>
</head>
<body>
   <p>DEMO3: 番号付き項目の二次元の並べ替え(ドラッグ&amp;ドロップで並べ替えられます。)</p>
<ul class="mylist">
    <li>
        <table>
            <tr>
                <th></th>
                <td>スター・ウォーズ</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>ゴッドファーザー</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>夕陽のガンマン</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>風と共に去りぬ</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>カサブランカ</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>レイダース/失われたアーク《聖櫃》</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>ロッキー</td>
            </tr>
        </table>
    </li>
    <li>
        <table>
            <tr>
                <th></th>
                <td>ロード・オブ・ザ・リング</td>
            </tr>
        </table>
    </li>

</ul>
<div style="clear: both;"></div>
<a href="https://www.udiscovermusic.jp/stories/the-50-best-film-scores-of-all-time">参考: 史上最高の映画音楽BEST50</a>

</body>
</html>
<script>
$(function(){
    $('.mylist').sortable();
});
</script>

二番目と同様に、liタグを使いますが、その中に二つしかセルがないtableを設置しています。

これで、二番目と同様に二次元の並べ替えができ、一番目と同様に自動で番号が振り付けられます。

細かいことですが、セルの中のテキストが長いと自動で折り返しされ、セルの高さがガタガタになってしまいますから、white-space: nowrap;を付けて折り返しがないようにしました。

また、そうすると今度はセルをテキストがはみ出しますから、overflow: hiddenを付けてはみ出すことがないようにしています。(切れたところの文字も読みたいようにするには、inputタグを組み込んだり、overflowの設定が必要でしょう。)

また、PCとスマホそれぞれで程よくみられるように、table幅などにvminの単位を使っています。

vminは、縦長に向けたスマホであれば、縦と比べて短い方の横幅が基準となり、PCであれば一般に短い方の画面の縦の高さが基準になります。

vminで40vminと指定することで、スマホであれば2項目が横に並びます。

PCでは3項目(横に長いスクリーンなら4項目かも)が並ぶでしょう。

もし「40%」という単位を使えば、PCでも2項目しか並ばないでしょう。

このように、レスポンシブデザインを考える時、vminの単位は便利です。(こういう用途のためにできた単位だと思います。)

まとめ

いかがでしたでしょうか。

JQueryを使えば、並べ替えがかなり簡単にできることがおわかりいただけたのではないでしょうか。

テーブルではtbodyのところにscriptでsortableと指定すれば可能です。

二次元の配置の場合も、リスト形式とし、liタグにfloatを指定し、ulタグなどにsortableとすれば可能となります。

また、番号はcounterのCSSをつければ、並べ替えても自動で振り直してくれます。これは二次元配置の場合も同様です。

このような並べ替えは、作業項目の優先順位の変更や、使いたい写真の優先度の変更などに応用可能ですから、ぜひ活用してみてください。