勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

SortableJSを使ってデータの並べ替え&保存

  PHP jQuery MySQL JavaScript

あるシステムを拝見した際にtableタグ内に並んでいる項目をドラッグ&ドロップで並べ替えする機能があった。ブラウザからソースを確認するとjQuery UIのSortable機能を使っているっぽい。ただ、jQuery UIを利用しなくてもSortable.jsは個別で利用できるようなので以下に使い方のメモ。

 

やりたいこと

tableタグ内の項目をドラッグ&ドロップで入れ替えて「変更」等のボタンをクリックすると並び順がMySQLに保存され、保存された並び順で表示される機能を実装したい。

 

サンプル

https://taitan916.info/sample/sortable/

 

Sortable.js

以下からダウンロードする。

https://github.com/SortableJS/Sortable

もしくはCDNで以下のように呼び出しても良い。

<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

 

ソース

<?php
//MySQL接続
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
$mysqli->set_charset('utf8');

//並び順変更処理
if( $_POST['order'] ){
	$data = json_decode($_POST['order'], true);

	foreach( $data as $key => $val ){
		$sql = '
			UPDATE sort_table  
			SET `order` = "' . $mysqli->real_escape_string($val) . '"
			WHERE id = "' . $mysqli->real_escape_string($key) . '"
		';
		$row = $mysqli->query($sql);
	}

	//ページリロード防止用
	header('Location:./');
	exit();
}

$sql = '
	SELECT * 
	FROM sort_table 
	ORDER BY `order` ASC
';
$row = $mysqli->query($sql);
while ($rs = $row->fetch_array(MYSQLI_ASSOC)) {
	$data[$rs['id']] = $rs;
}
?>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sortable サンプル</title>
</head>
<body>
<link href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-3.5.1.js"></script>
<style>
td{
	cursor: move;
}
</style>
<form action="./" method="post" id="order_form">
	<table>
		<tbody id="sort-table">
			<?php foreach( $data as $key => $val ){ ?>
				<tr class="id_<?php echo $val['id'];?>">
					<td><?php echo $val['order'];?></td>
					<td><?php echo $val['name'];?></td>
				</tr>
			<?php } ?>
		</tbody>
	</table>
	<input type="hidden" name="order" class="order" value="">
	<input type="submit" class="btn btn-success" value="順番を変更" onClick="return sortCheck();">
</form>
<script>
	//Sortable
	let table = document.getElementById('sort-table');
	Sortable.create(table);

	//並び順の処理
	function sortCheck(){
		let data = $('#sort-table > tr');
		let query = new Object();

		for( let i = 0; i < data.length; i++ ){
			//オブジェクトにkey = id / val = 並び順を格納
			query[data[i].attributes.class.value.replace('id_', '')] = i + 1;
		}

		//データをJSON化してinput="hidden"に格納
		$('.order').val(JSON.stringify(query));

		//フォーム送信
		$('#order_form').submit();

		//IEの二重送信防止用
		return false;
	}
</script>
</body>
</html>

query[data[i].attributes.class.value.replace('id_', '')]のところがちょっと気持ち悪いが、綺麗にまとめられなかった。

 

所感

今まで並び順変更機能を実装する場合、テキストボックス(input type="text")に数値を入力する形で実装していた。そうすると同じ数値を入力していた場合や、数値が入っていない場合はどうするかとか考える必要があったが、Sortable.jsを使うことでその辺りの作業は必要なくなりそう。

とはいえページングありのページだとテキストボックス形式を使うしかなさそう。あと、Sortable.jsの方がUI的に親切に思えるが、こちら側としてはJSを沢山使うとブラウザによって(特にIEは)挙動が異なったりするので、ブラウザ毎のチェックや不具合が発生した際の修正の手間を考えると、どちらの形式でいくのか悩ましいところ。

 - PHP jQuery MySQL JavaScript

  関連記事

jQueryでセレクトメニューにcheckedをつける

セレクトメニュー(セレクトボックス)で特定の項目をデフォルトで選択しておきたかっ ...

Dropzone.jsを使って画像をドラッグ&ドロップでアップロードする方法

画像を複数枚ドラッグ&ドロップでアップロードしたかった。だいぶ前にDro ...

スマホ対応のjQueryのカラーピッカープラグイン「excolor」の利用方法

以前の記事でカラーピッカープラグインのことを書いたけどスマホでは使えない。なので ...

jQueryでjsonデータを処理(parseJSON)

他社が作成したシステムのちょっと改修案件があった。設置したもののどうも動かないと ...

jQueryプラグインでクリップボードにコピーする方法(clipboard.js)

ページ上のボタンをクリックすることで特定の文章をクリップボードにコピーしたかった ...