/**
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
*/
|
|
var Utils = $.fn.bootstrapTable.utils
|
|
function printPageBuilderDefault (table) {
|
return `
|
<html>
|
<head>
|
<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>`
|
}
|
|
$.extend($.fn.bootstrapTable.locales, {
|
formatPrint () {
|
return 'Print'
|
}
|
})
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
|
$.extend($.fn.bootstrapTable.defaults, {
|
showPrint: false,
|
printAsFilteredAndSortedOnUI: true,
|
printSortColumn: undefined,
|
printSortOrder: 'asc',
|
printPageBuilder (table) {
|
return printPageBuilderDefault(table)
|
}
|
})
|
|
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
|
printFilter: undefined,
|
printIgnore: false,
|
printFormatter: undefined
|
})
|
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
print: {
|
bootstrap3: 'glyphicon-print icon-share',
|
'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 formatValue = (row, i, column) => {
|
const value = Utils.calculateObjectValue(column,
|
column.printFormatter || column.formatter,
|
[$.common.getItemField(row, column.field), row, i], $.common.getItemField(row, column.field))
|
|
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 (!columns[h].printIgnore) {
|
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 dontRender = []
|
|
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
|
|
dontRender.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 (
|
!columns[j].printIgnore && columns[j].field &&
|
(
|
!dontRender.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 (!columns[h].printIgnore) {
|
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('')
|
|
newWin.document.write(this.options.printPageBuilder.call(this, table))
|
newWin.document.close()
|
newWin.focus()
|
newWin.print()
|
newWin.close()
|
}
|
}
|