JavaScript 表格拖放排序 AJAX 資料庫 for PHP

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 更新資料庫使用
/*
 * 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
        ));
    }
}

線上

下載

參考

在〈JavaScript 表格拖放排序 AJAX 資料庫 for PHP〉中有 6 則留言

  1. 這個程式很好用,但是在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中無法拖曳。

        感謝您提供這麼好的程式,並熱心的指導。

發表留言