输入分页插件
DataTables 2 引入了 功能 的概念,这些功能是与 layout 选项一起放置在表格周围的表格控件和信息组件。有几个内置功能,一些 扩展 添加了它们自己的功能,但我想利用这篇博文来介绍 DataTables 的一个新型功能插件,展示它的功能,并且详细说明为 DataTables 制作功能插件有多么容易。
这里要介绍的功能插件被称为 InputPaging,它提供一个控件,可以替换内置 paging 功能。它的功能包括
- 向最终用户展示当前页码
- 允许最终用户键入他们想要查看的页码
- 可选的上一个/下一个按钮
- 可选的第一个/最后一个按钮
- 可选的总页数
- 自动与 DataTable 的默认样式、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 Hurst | Javascript 开发者 | 旧金山 | $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 Bruce | Javascript 开发者 | 新加坡 | $183,000 |
| Donna Snider | 客服 | 纽约 | $112,000 |
用法
在详细介绍如何创建你自己的自定义功能插件之前,让我们探索如何使用 InputPaging 插件。
初始化
此示例的初始化非常简单
new DataTable('#inputPaging', {
layout: {
bottomEnd: 'inputPaging'
}
});
请注意,此示例在新分页控件的底部使用新分页控件替换默认的 paging 控件。由于 layout 的工作原理,因此有可能在表格的上方和下方同时显示此控件,或者根据需要显示默认分页功能以及此功能!
来源
此插件的源代码在 DataTables 插件Git 仓库 中提供,并根据 MIT 许可证发布。可直接在你的页面中包含的分发文件在 DataTables CDN 上提供
如果您正在使用打包器,则此插件在 npm 上可通过 datatables.net-feature-inputpaging 获得。要将它与 ES 模块一起使用,只需包含该软件包,它便会将自身注册为可用功能
import DataTable from 'datatables.net-dt';
import 'datatables.net-feature-inputpaging';
new DataTable('#example', {
layout: {
bottomEnd: 'inputPaging'
}
});
此 StackBlitz 示例演示了如何在 Typescript + Vite 构建环境中使用此新插件。
选项
inputPaging 功能有三个选项
booleanfirstLast控制是否显示第一个和最后一个按钮booleanpreviousNext控制是否显示上一个和下一个按钮booleanpageOf控制是否在输入当前页码后立即显示/ {pages}文本。
要设置选项,请在 layout 中使用 inputPaging 选项作为对象 - 例如
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 的默认样式处理,因此我们需要使用与 paging 控件相同的结构。这是我们想要的部分
<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>
在纯粹的 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;
}
然后创建“first”按钮可能类似于以下内容。请注意 i18n 用途,以便获取为第一个分页按钮定义的语言字符串。这确保了与 DataTable 的现有选项完全集成。此外,page() 在事件处理程序中用于触发页面更改。
let first = createElement(
'button',
'dt-paging',
api.i18n('oPaginate.sFirst', '\u00AB'),
() => api.page('first').draw(false)
);
每个按钮都创建,然后附加到父元素,它从特征创建函数返回。尽管使用了辅助函数,此代码仍然相当冗余,因此为了简洁,请参见 此处代码。
Input 事件处理程序
这开始变得越来越有趣。只有数字值在 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 事件,在此事件中我们需要使用以下操作更新控件
- 可视化指示任何按钮是否已禁用(例如,当已在第一页时没有必要允许单击“First”按钮!)。这只需向上面创建的按钮添加或删除
disabled类即可完成。page.info()方法用于获取用于这些逻辑检查的数据。 - 接下来,如果外部操作更改了当前页面(例如,搜索将重置分页),我们需要将新值写入
input,以便终端用户可以看到他们所在的页面。 - 最后,总页码指示器需要更新,同样使用来自
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 结构,它因每个样式框架而异。
创建您自己的插件
如果您深受启发并创建了自己的 Feature 插件,请联系我们,并与社区分享!我很想看看您能做出什么。