jquery 封装 bootstrap table [完善]
效果如图:
JS 如下:
$.fn.extend({
pagination: function (opts) {
// The default config
const _defaultConfig = {
page: 1,
limit: 10,
maxDisplayCount: 5,
buttons: ['first', 'prev', 'next', 'last'],
}
const _config = $.extend({}, _defaultConfig, opts); // The pagination config
const that = this; // The pagination element
let { buttons = _defaultConfig.buttons } = opts || {} // The pagination buttons
let availableButtons = buttons.map((v, i, arr) => buttons.includes(v) ? v : '') // The available pagination buttons
let { change } = opts || {} // The event handler
let {
page = _defaultConfig.page, // The current page index
pageCount = 1, // The total page count
limit = _defaultConfig.limit, // The page size
} = opts
let { data = [] } = opts || {} // The data array
const $rootEle = $(this)
function init() {
delete _config.page
if (limit < 1)
limit = _defaultConfig.limit
if (Array.isArray(data) && data.length > 0)
pageCount = Math.ceil(data.length / limit)
renderPagination()
initEvent()
}
function initEvent() {
$rootEle.off('click', 'li.page-item')
$rootEle.on('click', 'li.page-item', function (e) {
const $this = $(this)
if ($this.hasClass('disabled'))
return;
if ($this.hasClass('active'))
return;
if ($this.hasClass('page-item')) {
if ($this.hasClass('first')) {
page = page = 1
} else if ($this.hasClass('prev')) {
if (page > 1) {
page = page -= 1
}
} else if ($this.hasClass('next')) {
if (page < pageCount) {
page = page += 1
}
} else if ($this.hasClass('last')) {
page = page = pageCount
}
if ($this.data('index') > 0) {
page = $this.data('index')
}
}
renderPagination()
if (change) {
change.call(that, e, {
page,
pageCount,
limit
})
}
})
}
function renderPagination() {
let _numberButtons = ``
for (let i = 0; i < pageCount; i++) {
const _pageIndex = ` data-index="${i + 1}"`
const _active = page === i + 1 ? ' active' : ''
_numberButtons += `<li class="page-item${_active}"${_pageIndex}><a class="page-link" href="#">${i + 1}</a></li>`
}
const _renderJumpButton = (index, disabled = false) => {
disabled = disabled ? ' disabled' : ''
const jumpName = availableButtons[index] ? ` ${availableButtons[index]}` : ''
return `<li class="page-item${jumpName}${disabled}"><a class="page-link" href="#">${availableButtons[index]}</a></li>`
}
const _renderButtons = () => {
let html = ``
if (availableButtons[0])
html += _renderJumpButton(0, page === 1)
if (availableButtons[1])
html += _renderJumpButton(1, page === 1)
html += _numberButtons
if (availableButtons[2])
html += _renderJumpButton(2, page === pageCount)
if (availableButtons[3])
html += _renderJumpButton(3, page === pageCount)
return html
}
const _paginationHtml = `<ul class="pagination">${_renderButtons()}</ul>`
$rootEle.html(_paginationHtml)
}
const render = function (options) {
const _opts = $.extend({}, opts, options)
return $rootEle.pagination.call(that, _opts)
}
init()
return {
page,
config: _config,
render,
}
},
table: function (opts) {
// The default config
const _defaultConfig = {
page: 1,
limit: 10,
}
const _config = $.extend({}, _defaultConfig, opts); // The table config
const that = this; // The table element
let { data = [], ajax = {}, pagination } = opts || {} // The table data
const { cols, limit = _defaultConfig.limit } = opts || {} // The table columns
// The pagination component
let _pagination
const paginationOptions = pagination // The pagination options
if (!data) {
data = []
}
// Find the table elements
const $rootEle = $(this)
const $tHead = $rootEle.find('thead')
const $tBody = $rootEle.find('tbody')
function init() {
initPagination()
renderTableHead()
renderTableBody()
pullData();
}
function initPagination() {
// The pagination component
if (paginationOptions) {
const pageEleSelector = paginationOptions.elem
if (!_config.limit || _config.limit < 1) {
_config.limit = _defaultConfig.limit
}
const _paginationChange = paginationOptions.change;
paginationOptions.change = (e, { page, pageCount, limit }) => {
if (_paginationChange)
_paginationChange.call(_pagination, e, { page, pageCount, limit });
pageChange(e, { page, pageCount, limit })
}
_pagination = $(pageEleSelector).pagination(paginationOptions)
}
}
// #region Render
function renderTableHead() {
const ths = cols.map(z => {
const sortable = z.sort ? ` sortable` : ''
const dataField = ` data-field="${z.field}"` || ''
return `<th scope="col"${dataField}${sortable}>${z.title || ''}</th>`
})
$tHead.html(`<tr>${ths.join('')}</tr>`)
}
function renderTableBody() {
const renderRows = getPendingRenderRows()
let _trs = renderRows.map((row, i) => {
const _cols = cols.map((col, j) => {
if (col.type === 'index') {
const checkbox = col.checkbox ? `<input type="checkbox" style="margin-right: 7px;" />` : ''
return `<th scope="row">${checkbox}${i + 1}</th>`
}
return `<td>${row[col.field] || ''}</td>`
})
return `<tr data-index="${i}">${_cols.join('')}</tr>`
})
if (renderRows.length < 1) {
_trs.push(`<tr><td colspan="${cols.length}" style="text-align: center;">暂无数据</td></tr>`)
}
$tBody.html(_trs.join(''))
}
function pageChange(e, { page, pageCount, limit }) {
_config.page = page
_config.limit = limit
renderTableBody()
}
// #endregion
// #region Utils
const getPagedRows = (rows) => {
const pageIndex = _config.page;
const pageSize = _config.limit;
const startIndex = (pageIndex - 1) * pageSize;
const stopIndex = startIndex + pageSize;
return (rows || data).slice(startIndex, stopIndex);
}
const getPendingRenderRows = () => {
if (limit) {
return getPagedRows()
}
return data
}
//#endregion
// #region Interfaces
const render = function (options) {
const _opts = $.extend({}, opts, options)
return $rootEle.table(_opts)
}
const pullData = function (options) {
if (!ajax || !ajax.url) {
console.error('ajax.url is required')
return;
}
// The ajax options backup
const _ajaxOptionsBackup = $.extend({}, ajax, options)
// The ajax options
const ajaxOptions = $.extend({}, _ajaxOptionsBackup)
const successCallback = function (res) {
if (_ajaxOptionsBackup.parseData && typeof _ajaxOptionsBackup.parseData === 'function') {
res = _ajaxOptionsBackup.parseData.call(that, res)
}
if (_ajaxOptionsBackup.success)
_ajaxOptionsBackup.success.call(that, res)
if (_ajaxOptionsBackup.done) {
data = _ajaxOptionsBackup.done.call(that, res)
}
if (Array.isArray(data)) {
renderTableBody()
if (_pagination) {
_pagination = _pagination.render({ data: data })
}
} else {
console.error('data must be array')
}
}
ajaxOptions.success = successCallback
const errorCallback = function (res) {
if (_ajaxOptionsBackup.error)
_ajaxOptionsBackup.error.call(that, res)
}
ajaxOptions.error = errorCallback
const completeCallback = function (res) {
if (_ajaxOptionsBackup.complete)
_ajaxOptionsBackup.complete.call(that, res)
}
ajaxOptions.complete = completeCallback
$.ajax(ajaxOptions)
}
// #endregion
init()
return {
config: _config,
render,
pullData,
}
},
})
HTML:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>jquery-table</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous" />
<style>
body,
#root {
width: 100vw;
height: 100vh;
box-sizing: border-box;
overflow: hidden;
}
#root {
display: flex;
place-items: center;
}
</style>
</head>
<body>
<div id="root">
<div class="container">
<table id="jTable" class="table table-striped table-dark" style="position: relative;">
<thead> </thead>
<tbody> </tbody>
</table>
<!-- <div class="d-flex justify-content-center" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 999; background-color: rgba(255, 255, 255, 0.5);">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> -->
<nav id="jPagination" class="d-flex justify-content-center" aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
<!-- <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script> -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-7ymO4nGrkm372HoSbq1OY2DP4pEZnMiA+E0F3zPr+JQQtQ82gQ1HPY3QIVtztVua"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Mock.js/1.0.1-beta1/mock-min.js"
integrity="sha512-C6haFoe26x0I8R2daqjCKMYlOvq++RXhACOBluxWpZdScv5kuIMrQtxAVweoRqWUlvF0bKtCSEI0f561tRQhtw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="/table.js"> </script>
<script>
Mock.mock(/data\.json/, {
'data|36': [{
'id|+1': 1,
'name': '@cname',
'gender|1': ['boy', 'girl'],
'age|15-23': 15,
'city': '@province',
'phone': /^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$/,
'email': '@email',
'identity': /[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]/,
}]
})
const cols = [
{
type: 'index',
checkbox: true,
title: '#'
},
{
field: 'name',
title: 'name',
sort: true,
},
{
field: 'gender',
title: 'gender',
sort: true,
},
{
field: 'age',
title: 'age',
sort: true,
},
{
field: 'city',
title: 'city',
sort: true,
},
{
field: 'phone',
title: 'phone',
sort: true,
},
{
field: 'email',
title: 'email',
sort: true,
},
{
field: 'identity',
title: 'identity',
sort: true,
},
]
const table = $('#jTable').table({
pagination: {
elem: '#jPagination',
},
// data: data,
ajax: {
url: './data.json',
method: 'POST',
dataType: 'json',
done: function (res) {
return res.data;
},
},
cols: cols,
limit: 10,
events: {
'action-delete': function (row) {
},
'action-check': function (row) {
}
}
})
console.log(table);
</script>
</body>
</html>