JavaScript 表格拖放排序 AJAX 資料庫 for PHP
說明如何使用原生 JavaScript 的 HTML5 Drag and Drop API(拖放操作 API),進行表格拖放排序,且搭配 AJAX 與 PHP 來同步更新資料庫,達到即時排序功能,並提供線上與下載範例。
HTML 拖放操作 API
之前要讓網頁有拖放功能,通常都需使用 jQuery Plugin(例如 Table Drag and Drop jQuery plugin)來完成。
HTML5 定義了很多有用的 APIs,而 Drag and Drop API(拖放操作 API)是其中一個,可用它來拖放網頁元素。
範例
針對程式的主要部分與運作原理說明。
程式
HTML
除了文字、圖片或超連結,預設可拖拉外,其它元素要可以拖拉必須設定 draggable="true"
屬性。
如果要讓 <tr>
元素可進行拖拉:
<table id="draggable">
<thead>
<tr>
<th>ID</th>
<th>Sort</th>
<th>Name</th>
<th>Height</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr class="data" draggable="true">
<td class="id">1</td>
<td class="sort">0</td>
<td>Jacky</td>
<td>172</td>
<td>54</td>
</tr>
<tr class="data" draggable="true">
<td class="id">2</td>
<td class="sort">1</td>
<td>Kevin</td>
<td>175</td>
<td>60</td>
</tr>
</tbody>
</table>
JavaScript
使用者對網頁元素進行拖放操作時:
- 變更 CSS 樣式與元素的排序
- 放開元素時,AJAX 當前所有 ID 的排序,讓後續 PHP 更新資料庫使用
使用 jQuery 的 AJAX 功能
/*
* HTML Drag and Drop API(拖、放操作 API)
*/
var dragged; // 保存拖動元素的引用(ref.),就是拖動元素本身
// 當開始拖動一個元素或一個選擇文本的時候 dragstart 事件就會觸發(設定拖動資料和拖動用的影像,且當從 OS 拖動檔案進入瀏覽器時不會觸發)
document.addEventListener('dragstart', function(event) {
dragged = event.target;
event.target.style.backgroundColor = 'rgba(240, 240, 240, 0.5)';
event.target.style.color = 'rgba(255, 255, 255, 0.5)';
}, false);
// 不論結果如何,拖動作業結束當下,被拖動元素都會收到一個 dragend 事件(當從 OS 拖動檔案進入瀏覽器時不會觸發)
document.addEventListener('dragend', function(event) {
// 重置樣式
event.target.style.backgroundColor = '#222222';
event.target.style.color = '#ffffff';
}, false);
// 當一個元素或者文本被拖動到有效放置目標 dragover 事件就會一直觸發(每隔幾百毫秒)
// 絕大多數的元素預設事件都不准丟放資料,所以想要丟放資料到元素上,就必須取消預設事件行為
// 取消預設事件行為能夠藉由呼叫 event.preventDefault 方法
document.addEventListener('dragover', function(event) {
// 阻止預設事件行為
event.preventDefault();
}, false);
// 當拖動的元素或者文本進入一個有效的放置目標 dragenter 事件就會觸發
document.addEventListener('dragenter', function(event) {
// 當拖動的元素進入可放置的目標(自訂符合條件),變更背景顏色
// 自訂條件:class 名稱 && 不是本身的元素
if (event.target.parentNode.className == 'data' &&
dragged !== event.target.parentNode) {
dragged.style.background = 'purple';
// 判斷向下或向上拖動,來決定在元素前或後插入元素
if (dragged.rowIndex < event.target.parentNode.rowIndex) {
event.target.parentNode.parentNode.insertBefore(dragged, event.target.parentNode.nextSibling);
}
else {
event.target.parentNode.parentNode.insertBefore(dragged, event.target.parentNode);
}
}
}, false);
// 當拖動的元素或者文本離開有效的放置目標 dragleave 事件就會觸發
document.addEventListener('dragleave', function(event) {
// 當拖動元素離開可放置目標節點,重置背景
// 自訂條件:class 名稱 && 不是本身的元素
if (event.target.parentNode.className == 'data' &&
dragged !== event.target.parentNode) {
// 當拖動元素離開可放置目標節點,重置背景
event.target.parentNode.style.background = '';
}
}, false);
// 當丟放拖動元素到拖拉目標區時 drop 事件就會觸發;此時事件處理器可能會需要取出拖拉資料並處理之
// 這個事件只有在被允許下才會觸發,如果在使用者取消拖拉操作時,如按 ESC 鍵或滑鼠不是在拖拉目標元素上,此事件不會觸發
document.addEventListener('drop', function(event) {
/*
* AJAX Update DB
*/
var id = document.querySelectorAll('.id');
var data = []; // 儲存所有 ID
for (var i = 0, len = id.length; i < len; i++) {
// 取得所有 ID 並存為 array
data.push(id[i].innerHTML);
// 重新排序表格 Sort 數值
id[i].parentNode.querySelector('.sort').innerHTML = i;
}
// jQuery AJAX
$.get('ajax.php', {"data": data});
}, false);
PHP
接收 AJAX 過來的 ID,並依順序重新排序資料庫裡所有資料的更新。
<?php
/**
* AJAX 更新排序
*/
if (isset($_REQUEST['data'])) {
// PDO 連結
include_once 'pdo-conn.php';
$sql = 'UPDATE drag_drop
SET sort = :sort
WHERE ID = :ID';
$stmt = $dbConn->prepare($sql);
// 更新所有資料排序
foreach ($_REQUEST['data'] as $key => $value) {
$stmt->execute(array(
'sort' => $key,
'ID' => $value
));
}
}
線上
下載
參考
本著作係採用創用 CC 姓名標示-相同方式分享 3.0 台灣 授權條款授權.
谢谢你。 非常的有用
這個程式很好用,但是在firefox上無法拖曳,應如何解決。我的firefox是V62.0版。
您可能需先確認 Firefox:
1. 版本是否支援 Drag and Drop API。
2. 使用瀏覽器控制台查看顯示的 Error 訊息。
爬了一些文章匯整如下:
在javascript中加入
function dragstart_handler(ev) {
//console.log("dragStart");
ev.dataTransfer.setData("text", ev.target.id);
ev.effectAllowed = "copyMove";
}
另外在被拖曳的元素上除了draggable="true"還需加上ondragstart="dragstart_handler(event);",不加ondragstart在firefox中無法拖曳。
例
感謝您提供這麼好的程式,並熱心的指導。
能夠自己尋找問題並解決非常棒唷~