/**
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
*/
|
|
var Utils = $.fn.bootstrapTable.utils
|
|
function printPageBuilderDefault (table, styles) {
|
return `
|
<html>
|
<head>
|
${styles}
|
<style type="text/css" media="print">
|
@page {
|
size: auto;
|
margin: 25px 0 25px 0;
|
}
|
</style>
|
<style type="text/css" media="all">
|
table {
|
border-collapse: collapse;
|
font-size: 12px;
|
}
|
table, th, td {
|
border: 1px solid grey;
|
}
|
th, td {
|
text-align: center;
|
vertical-align: middle;
|
}
|
p {
|
font-weight: bold;
|
margin-left:20px;
|
}
|
table {
|
width: 94%;
|
margin-left: 3%;
|
margin-right: 3%;
|
}
|
div.bs-table-print {
|
text-align: center;
|
}
|
</style>
|
</head>
|
<title>Print Table</title>
|
<body>
|
<p>Printed on: ${new Date} </p>
|
<div class="bs-table-print">${table}</div>
|
</body>
|
</html>
|
`
|
}
|
|
Object.assign($.fn.bootstrapTable.locales, {
|
formatPrint () {
|
return 'Print'
|
}
|
})
|
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
|
Object.assign($.fn.bootstrapTable.defaults, {
|
showPrint: false,
|
printAsFilteredAndSortedOnUI: true,
|
printSortColumn: undefined,
|
printSortOrder: 'asc',
|
printStyles: [],
|
printPageBuilder (table, styles) {
|
return printPageBuilderDefault(table, styles)
|
}
|
})
|
|
Object.assign($.fn.bootstrapTable.columnDefaults, {
|
printFilter: undefined,
|
printIgnore: false,
|
printFormatter: undefined
|
})
|
|
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
print: {
|
bootstrap3: 'glyphicon-print icon-share',
|
bootstrap5: 'bi-printer',
|
'bootstrap-table': 'icon-printer'
|
}[$.fn.bootstrapTable.theme] || 'fa-print'
|
})
|
|
$.BootstrapTable = class extends $.BootstrapTable {
|
init (...args) {
|
super.init(...args)
|
|
if (!this.options.showPrint) {
|
return
|
}
|
|
this.mergedCells = []
|
}
|
|
initToolbar (...args) {
|
this.showToolbar = this.showToolbar || this.options.showPrint
|
|
if (this.options.showPrint) {
|
this.buttons = Object.assign(this.buttons, {
|
print: {
|
text: this.options.formatPrint(),
|
icon: this.options.icons.print,
|
event: () => {
|
this.doPrint(this.options.printAsFilteredAndSortedOnUI ? this.getData() : this.options.data.slice(0))
|
},
|
attributes: {
|
'aria-label': this.options.formatPrint(),
|
title: this.options.formatPrint()
|
}
|
}
|
})
|
}
|
|
super.initToolbar(...args)
|
}
|
|
mergeCells (options) {
|
super.mergeCells(options)
|
|
if (!this.options.showPrint) {
|
return
|
}
|
|
let col = this.getVisibleFields().indexOf(options.field)
|
|
if (Utils.hasDetailViewIcon(this.options)) {
|
col += 1
|
}
|
|
this.mergedCells.push({
|
row: options.index,
|
col,
|
rowspan: options.rowspan || 1,
|
colspan: options.colspan || 1
|
})
|
}
|
|
doPrint (data) {
|
const canPrint = column => {
|
return !column.printIgnore && column.visible
|
}
|
|
const formatValue = (row, i, column) => {
|
const value_ = Utils.getItemField(row, column.field, this.options.escape, column.escape)
|
const value = Utils.calculateObjectValue(column,
|
column.printFormatter || column.formatter,
|
[value_, row, i], value_)
|
|
return typeof value === 'undefined' || value === null ?
|
this.options.undefinedText : value
|
}
|
|
const buildTable = (data, columnsArray) => {
|
const dir = this.$el.attr('dir') || 'ltr'
|
const html = [`<table dir="${dir}"><thead>`]
|
|
for (const columns of columnsArray) {
|
html.push('<tr>')
|
for (let h = 0; h < columns.length; h++) {
|
if (canPrint(columns[h])) {
|
html.push(
|
`<th
|
${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
|
${Utils.sprintf(' colspan="%s"', columns[h].colspan)}
|
>${columns[h].title}</th>`)
|
}
|
}
|
html.push('</tr>')
|
}
|
|
html.push('</thead><tbody>')
|
|
const notRender = []
|
|
if (this.mergedCells) {
|
for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
const currentMergedCell = this.mergedCells[mc]
|
|
for (let rs = 0; rs < currentMergedCell.rowspan; rs++) {
|
const row = currentMergedCell.row + rs
|
|
for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
|
const col = currentMergedCell.col + cs
|
|
notRender.push(`${row},${col}`)
|
}
|
}
|
}
|
}
|
|
for (let i = 0; i < data.length; i++) {
|
html.push('<tr>')
|
|
const columns = columnsArray.flat(1)
|
|
columns.sort((c1, c2) => {
|
return c1.colspanIndex - c2.colspanIndex
|
})
|
|
for (let j = 0; j < columns.length; j++) {
|
if (columns[j].colspanGroup > 0) continue
|
|
let rowspan = 0
|
let colspan = 0
|
|
if (this.mergedCells) {
|
for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
const currentMergedCell = this.mergedCells[mc]
|
|
if (currentMergedCell.col === j && currentMergedCell.row === i) {
|
rowspan = currentMergedCell.rowspan
|
colspan = currentMergedCell.colspan
|
}
|
}
|
}
|
|
if (
|
canPrint(columns[j]) &&
|
(
|
!notRender.includes(`${i},${j}`) ||
|
rowspan > 0 && colspan > 0
|
)
|
) {
|
if (rowspan > 0 && colspan > 0) {
|
html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>')
|
} else {
|
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>')
|
}
|
}
|
}
|
|
html.push('</tr>')
|
}
|
|
html.push('</tbody>')
|
if (this.options.showFooter) {
|
html.push('<footer><tr>')
|
|
for (const columns of columnsArray) {
|
for (let h = 0; h < columns.length; h++) {
|
if (canPrint(columns)) {
|
const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr'))
|
const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '')
|
|
html.push(`<th>${footerValue}</th>`)
|
}
|
}
|
}
|
|
html.push('</tr></footer>')
|
}
|
html.push('</table>')
|
return html.join('')
|
}
|
|
const sortRows = (data, colName, sortOrder) => {
|
if (!colName) {
|
return data
|
}
|
let reverse = sortOrder !== 'asc'
|
|
reverse = -(+reverse || -1)
|
return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName]))
|
}
|
|
const filterRow = (row, filters) => {
|
for (let index = 0; index < filters.length; ++index) {
|
if (row[filters[index].colName] !== filters[index].value) {
|
return false
|
}
|
}
|
return true
|
}
|
|
const filterRows = (data, filters) => data.filter(row => filterRow(row, filters))
|
const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
|
colName: col.field,
|
value: col.printFilter
|
}))
|
|
data = filterRows(data, getColumnFilters(this.options.columns))
|
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
|
const table = buildTable(data, this.options.columns)
|
const newWin = window.open('')
|
const printStyles = typeof this.options.printStyles === 'string' ?
|
this.options.printStyles.replace(/\[|\]| /g, '').toLowerCase().split(',') :
|
this.options.printStyles
|
const styles = printStyles.map(it =>
|
`<link rel="stylesheet" href="${it}" />`).join('')
|
|
const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder,
|
[table, styles], printPageBuilderDefault(table, styles))
|
const startPrint = () => {
|
newWin.focus()
|
newWin.print()
|
newWin.close()
|
}
|
|
newWin.document.write(calculatedPrintPage)
|
newWin.document.close()
|
|
if (printStyles.length) {
|
const links = document.getElementsByTagName('link')
|
const lastLink = links[links.length - 1]
|
|
lastLink.onload = startPrint
|
} else {
|
startPrint()
|
}
|
}
|
}
|