2024 年 5 月 28 日星期二
作者:Allan Jardine

輸入分頁外掛

DataTables 2 引入了功能的概念,這些功能是表格控制和資訊元件,它們使用layout選項放置在表格周圍。有一些內建的功能,以及一些擴充套件會加入自己的功能,但我想藉由這篇部落格文章來介紹一個新的 DataTables 功能外掛,展示它的功能,並詳細說明製作 DataTables 功能外掛有多麼容易。

我將在這裡介紹的功能外掛稱為 InputPaging,它提供一個控制項,可以取代內建的分頁功能。它的功能包括:

  • 向終端使用者顯示目前頁碼
  • 允許終端使用者輸入他們想要檢視的頁碼
  • 可選的上一個/下一個按鈕
  • 可選的第一個/最後一個按鈕
  • 可選的總頁數計數
  • 自動與 DataTables 的預設樣式、Bootstrap 3/4/5、Bulma、Foundation、jQuery UI 和 FomanticUI 整合。

這是一個實際應用的範例(InputPaging 控制項位於表格的右下角)

姓名職位辦公室薪資
Tiger Nixon系統架構師愛丁堡$320,800
Garrett Winters會計師東京$170,750
Ashton Cox初級技術作家舊金山$86,000
Cedric Kelly資深 Javascript 開發人員愛丁堡$433,060
Airi Satou會計師東京$162,700
Brielle Williamson整合專員紐約$372,000
Herrod Chandler銷售助理舊金山$137,500
Rhona Davidson整合專員東京$327,900
Colleen HurstJavascript 開發人員舊金山$205,500
Sonya Frost軟體工程師愛丁堡$103,600
Jena Gaines辦公室經理倫敦$90,560
Quinn Flynn支援主管愛丁堡$342,000
Charde Marshall區域總監舊金山$470,600
Haley Kennedy資深行銷設計師倫敦$313,500
Tatyana Fitzpatrick區域總監倫敦$385,750
Michael Silva行銷設計師倫敦$198,500
Paul Byrd財務長 (CFO)紐約$725,000
Gloria Little系統管理員紐約$237,500
Bradley Greer軟體工程師倫敦$132,000
Dai Rios人事主管愛丁堡$217,500
Jenette Caldwell開發主管紐約$345,000
Yuri Berry行銷長 (CMO)紐約$675,000
Caesar Vance售前支援紐約$106,450
Doris Wilder銷售助理雪梨$85,600
Angelica Ramos執行長 (CEO)倫敦$1,200,000
Gavin Joyce開發人員愛丁堡$92,575
Jennifer Chang區域總監新加坡$357,650
Brenden Wagner軟體工程師舊金山$206,850
Fiona Green營運長 (COO)舊金山$850,000
Shou Itou區域行銷東京$163,000
Michelle House整合專員雪梨$95,400
Suki Burks開發人員倫敦$114,500
Prescott Bartlett技術作家倫敦$145,000
Gavin Cortez團隊領導舊金山$235,500
Martena Mccray售後支援愛丁堡$324,050
Unity Butler行銷設計師舊金山$85,675
Howard Hatfield辦公室經理舊金山$164,500
Hope Fuentes秘書舊金山$109,850
Vivian Harrell財務總監舊金山$452,500
Timothy Mooney辦公室經理倫敦$136,200
Jackson Bradshaw總監紐約$645,750
Olivia Liang支援工程師新加坡$234,500
Bruno Nash軟體工程師倫敦$163,500
Sakura Yamamoto支援工程師東京$139,575
Thor Walton開發人員紐約$98,540
Finn Camacho支援工程師舊金山$87,500
Serge Baldwin資料協調員新加坡$138,575
Zenaida Frank軟體工程師紐約$125,250
Zorita Serrano軟體工程師舊金山$115,000
Jennifer Acosta初級 Javascript 開發人員愛丁堡$75,650
Cara Stevens銷售助理紐約$145,600
Hermione Butler區域總監倫敦$356,250
Lael Greer系統管理員倫敦$103,500
Jonas Alexander開發人員舊金山$86,500
Shad Decker區域總監愛丁堡$183,000
Michael BruceJavascript 開發人員新加坡$183,000
Donna Snider客戶支援紐約$112,000

使用方式

在詳細說明如何建立自己的自訂功能外掛之前,讓我們先探討如何使用 InputPaging 外掛。

初始化

此範例的初始化非常簡單,使用以下程式碼:

new DataTable('#inputPaging', {
    layout: {
        bottomEnd: 'inputPaging'
    }
});

請注意,此範例使用新的分頁控制項取代預設的分頁控制項,該控制項通常位於表格的 bottomEnd。由於layout 的運作方式,可以讓此控制項同時顯示在表格的上方和下方,或者,如果您願意,也可以同時顯示預設的分頁功能和此控制項!

來源

此外掛的來源可在DataTables 外掛 git 儲存庫中取得,並以 MIT 授權發佈。要直接包含在您頁面上的發佈檔案可在 DataTables CDN 上取得

CSS
JS

如果您使用 bundler,則此外掛程式可在 npm 上以 datatables.net-feature-inputpaging 的名稱取得。若要與 ES Modules 一起使用,只需包含該套件,它就會將自己註冊為可用的功能

import DataTable from 'datatables.net-dt';
import 'datatables.net-feature-inputpaging';

new DataTable('#example', {
    layout: {
        bottomEnd: 'inputPaging'
    }
});

這個 StackBlitz 範例示範了如何在 Typescript + Vite 建置環境中使用新的外掛。

選項

inputPaging 功能有三個選項

  • boolean firstLast,控制是否顯示第一個最後一個按鈕
  • boolean previousNext,控制是否顯示上一個下一個按鈕
  • boolean pageOf,控制是否在目前頁碼的 input 之後立即顯示 / {pages} 文字。

若要設定選項,請將 inputPaging 選項用作layout中的物件 - 例如:

new DataTable('#example', {
    layout: {
        bottomEnd: {
            inputPaging: {
                pageOf: false
            }
        }
    }
});

建立功能外掛

建立 DataTables 的功能外掛非常簡單 - 使用 DataTable.feature.register() 靜態方法向 DataTables 註冊您的功能。參考文件提供了該方法的完整詳細資料,但基本上它有兩個參數:功能名稱(即如何在layout中參考它),以及一個函式,用於建立功能的 DOM 元素和事件監聽器。此函式應傳回一個 DOM 節點,並傳入兩個參數:DataTable 設定物件和功能的選項。

在程式碼中更容易理解:

DataTable.feature.register('myToolbar', function (settings, opts) {
    // Define defaults
    let options = Object.assign({
        option1: false,
        option2: false
    }, opts);
 
    let container = document.createElement('div');
 
    // do something with the options and container
    // ...
 
    return container;
});

就這樣 - 您已經建立了一個 DataTables 功能外掛!現在讓我們來探討如何建立分頁控制項。

DOM 元素

我們需要建立幾個具有事件處理器的 DOM 元素。為了此處的討論,我們將使用 DataTables 的預設樣式,因此我們需要使用與分頁控制項相同的結構。這就是我們想要的:

<div class="dt-inputpaging dt-paging">
    <button class="dt-paging-button disabled">«</button>
    <button class="dt-paging-button disabled">‹</button>
    <div class="dt-paging-input">
        <input class="" type="text" inputmode="numeric" pattern="[0-9]*" style="width: 3ch;">
        <span class=""> / 6</span>
    </div>
    <button class="dt-paging-button">›</button>
    <button class="dt-paging-button">»</button>
</div>

在 vanilla JS 中建立 DOM 節點始終是一項冗長的程式碼操作,因此讓我們為它建立一個輔助函式:

/**
 * Create a new element
 *
 * @param tag Tag name
 * @param className Class to assign
 * @param text Text to show in the element
 * @param fn Click event handler
 * @returns Element
 */
function createElement(tag, className, text, fn) {
    var el = document.createElement(tag);

    if (className) {
        el.className = className;
    }

    if (text) {
        el.textContent = text;
    }

    if (fn) {
        el.addEventListener('click', fn);
    }

    return el;
}

然後建立「第一個」按鈕可能會如下所示。請注意使用 i18n 來取得為第一個分頁按鈕定義的語言字串。這確保與 DataTable 的現有選項完全整合。此外,page() 用於事件處理器中以觸發頁面變更。

let first = createElement(
    'button',
    'dt-paging',
    api.i18n('oPaginate.sFirst', '\u00AB'),
    () => api.page('first').draw(false)
);

每個按鈕都會被建立,然後附加到父元素,也就是從功能建立函式傳回的元素。儘管使用了輔助函式,但此程式碼仍然相當冗長,因此為了簡潔起見,請參閱此處的程式碼

輸入事件處理器

這才是開始變得更有趣的地方。只有數字值與input元素相關,因此我們可以使用事件處理器來停用終端使用者輸入非數字字元的功能:

// Block characters other than numbers
input.addEventListener('keypress', function (e) {
    if (e.charCode < 48 || e.charCode > 57) {
        e.preventDefault();
    }
});

當終端使用者在input中輸入新數字時,我們還想執行兩個動作。第一個很明顯 - 我們需要使用 page() 將 DataTable 的顯示頁面變更為新數字(如果終端使用者輸入不存在的頁面,它具有內建的更正功能)。

第二個動作是調整 input 的寬度以符合內容。這對終端使用者很有用,因為它讓他們可以查看完整的頁碼,而不會佔用比所需更多的寬度(這很重要,因為它允許具有數百萬行的表格)。為此,我們使用字串中的字元數和 ch 單位,這是 0 的寬度(類似於 em,但用於數字!)

// On new value, redraw the table
input.addEventListener('input', function () {
    if (input.value) {
        api.page(input.value - 1).draw(false);
    }

    // Auto adjust the width so the content is visible
    input.style.width = (input.value.length + 2) + 'ch';
});

DataTables 事件

最後,當繪製 DataTable 時,它會發出draw事件,此時我們需要使用以下動作更新我們的控制項:

  1. 視覺上指示是否有任何按鈕被停用(例如,當已經在第一頁時,點擊「第一個」按鈕沒有意義!)。這只需從上面建立的按鈕新增或移除 disabled 類別即可完成。 page.info() 方法用於取得用於這些邏輯檢查的資料。
  2. 接下來,如果外部操作變更目前頁面(例如,搜尋將重設分頁),我們需要將新值寫入 input 中,以便終端使用者可以看到他們所在的頁面。
  3. 最後,總頁數指示器也需要更新,同樣使用來自 page.info() 的資訊。
api.on('draw', () => {
    let info = api.page.info();

    // Update the classes for the "jump" buttons to show what is available
    first.classList.toggle('disabled', info.page === 0);
    previous.classList.toggle('disabled', info.page === 0);
    next.classList.toggle('disabled', info.page === info.pages-1);
    last.classList.toggle('disabled', info.page === info.pages-1);

    // Set the new page value into the input box
    if (input.value !== info.page + 1) {
        input.value = info.page + 1;
    }

    // Show how many pages there are
    of.textContent = ' / ' + info.pages;
});

這只是開始

上面建立的程式碼完整清單可以在這裡找到。您可能已經注意到,此程式碼沒有考慮 DataTables 支援的不同樣式架構,例如 Bootstrap 和 Bulma。我簡化了完整功能外掛程式所使用的實際程式碼,以使此討論更易於管理!如果您有興趣,請查看此外掛程式的原始碼- 關鍵在於如何處理 DOM 結構,每個樣式架構的 DOM 結構略有不同。

建立您自己的外掛程式

如果您受到啟發並建立了您自己的功能外掛程式,請聯絡我們並與社群分享!我很想看看您可以做出什麼。