1 |
|
2 |
|
3 |
|
4 |
|
5 | const Utils = $.fn.bootstrapTable.utils
|
6 |
|
7 | function printPageBuilderDefault (table) {
|
8 | return `
|
9 | <html>
|
10 | <head>
|
11 | <style type="text/css" media="print">
|
12 | @page {
|
13 | size: auto;
|
14 | margin: 25px 0 25px 0;
|
15 | }
|
16 | </style>
|
17 | <style type="text/css" media="all">
|
18 | table {
|
19 | border-collapse: collapse;
|
20 | font-size: 12px;
|
21 | }
|
22 | table, th, td {
|
23 | border: 1px solid grey;
|
24 | }
|
25 | th, td {
|
26 | text-align: center;
|
27 | vertical-align: middle;
|
28 | }
|
29 | p {
|
30 | font-weight: bold;
|
31 | margin-left:20px;
|
32 | }
|
33 | table {
|
34 | width:94%;
|
35 | margin-left:3%;
|
36 | margin-right:3%;
|
37 | }
|
38 | div.bs-table-print {
|
39 | text-align:center;
|
40 | }
|
41 | </style>
|
42 | </head>
|
43 | <title>Print Table</title>
|
44 | <body>
|
45 | <p>Printed on: ${new Date} </p>
|
46 | <div class="bs-table-print">${table}</div>
|
47 | </body>
|
48 | </html>`
|
49 | }
|
50 |
|
51 | Object.assign($.fn.bootstrapTable.locales, {
|
52 | formatPrint () {
|
53 | return 'Print'
|
54 | }
|
55 | })
|
56 | Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
57 |
|
58 | Object.assign($.fn.bootstrapTable.defaults, {
|
59 | showPrint: false,
|
60 | printAsFilteredAndSortedOnUI: true,
|
61 | printSortColumn: undefined,
|
62 | printSortOrder: 'asc',
|
63 | printPageBuilder (table) {
|
64 | return printPageBuilderDefault(table)
|
65 | }
|
66 | })
|
67 |
|
68 | Object.assign($.fn.bootstrapTable.columnDefaults, {
|
69 | printFilter: undefined,
|
70 | printIgnore: false,
|
71 | printFormatter: undefined
|
72 | })
|
73 |
|
74 | Object.assign($.fn.bootstrapTable.defaults.icons, {
|
75 | print: {
|
76 | bootstrap3: 'glyphicon-print icon-share',
|
77 | bootstrap5: 'bi-printer',
|
78 | 'bootstrap-table': 'icon-printer'
|
79 | }[$.fn.bootstrapTable.theme] || 'fa-print'
|
80 | })
|
81 |
|
82 | $.BootstrapTable = class extends $.BootstrapTable {
|
83 | init (...args) {
|
84 | super.init(...args)
|
85 |
|
86 | if (!this.options.showPrint) {
|
87 | return
|
88 | }
|
89 |
|
90 | this.mergedCells = []
|
91 | }
|
92 |
|
93 | initToolbar (...args) {
|
94 | this.showToolbar = this.showToolbar || this.options.showPrint
|
95 |
|
96 | if (this.options.showPrint) {
|
97 | this.buttons = Object.assign(this.buttons, {
|
98 | print: {
|
99 | text: this.options.formatPrint(),
|
100 | icon: this.options.icons.print,
|
101 | event: () => {
|
102 | this.doPrint(this.options.printAsFilteredAndSortedOnUI ? this.getData() : this.options.data.slice(0))
|
103 | },
|
104 | attributes: {
|
105 | 'aria-label': this.options.formatPrint(),
|
106 | title: this.options.formatPrint()
|
107 | }
|
108 | }
|
109 | })
|
110 | }
|
111 |
|
112 | super.initToolbar(...args)
|
113 | }
|
114 |
|
115 | mergeCells (options) {
|
116 | super.mergeCells(options)
|
117 |
|
118 | if (!this.options.showPrint) {
|
119 | return
|
120 | }
|
121 |
|
122 | let col = this.getVisibleFields().indexOf(options.field)
|
123 |
|
124 | if (Utils.hasDetailViewIcon(this.options)) {
|
125 | col += 1
|
126 | }
|
127 |
|
128 | this.mergedCells.push({
|
129 | row: options.index,
|
130 | col,
|
131 | rowspan: options.rowspan || 1,
|
132 | colspan: options.colspan || 1
|
133 | })
|
134 | }
|
135 |
|
136 | doPrint (data) {
|
137 | const _this2 = this
|
138 | const formatValue = (row, i, column) => {
|
139 | const value_ = Utils.getItemField(row, column.field, _this2.options.escape, column.escape)
|
140 | const value = Utils.calculateObjectValue(column,
|
141 | column.printFormatter || column.formatter,
|
142 | [value_, row, i], value_)
|
143 |
|
144 | return typeof value === 'undefined' || value === null ?
|
145 | this.options.undefinedText : value
|
146 | }
|
147 |
|
148 | const buildTable = (data, columnsArray) => {
|
149 | const dir = this.$el.attr('dir') || 'ltr'
|
150 | const html = [`<table dir="${dir}"><thead>`]
|
151 |
|
152 | for (const columns of columnsArray) {
|
153 | html.push('<tr>')
|
154 | for (let h = 0; h < columns.length; h++) {
|
155 | if (!columns[h].printIgnore && columns[h].visible) {
|
156 | html.push(
|
157 | `<th
|
158 | ${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
|
159 | ${Utils.sprintf(' colspan="%s"', columns[h].colspan)}
|
160 | >${columns[h].title}</th>`)
|
161 | }
|
162 | }
|
163 | html.push('</tr>')
|
164 | }
|
165 |
|
166 | html.push('</thead><tbody>')
|
167 |
|
168 | const dontRender = []
|
169 |
|
170 | if (this.mergedCells) {
|
171 | for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
172 | const currentMergedCell = this.mergedCells[mc]
|
173 |
|
174 | for (let rs = 0; rs < currentMergedCell.rowspan; rs++) {
|
175 | const row = currentMergedCell.row + rs
|
176 |
|
177 | for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
|
178 | const col = currentMergedCell.col + cs
|
179 |
|
180 | dontRender.push(`${row},${col}`)
|
181 | }
|
182 | }
|
183 | }
|
184 | }
|
185 |
|
186 | for (let i = 0; i < data.length; i++) {
|
187 | html.push('<tr>')
|
188 |
|
189 | const columns = columnsArray.flat(1)
|
190 |
|
191 | columns.sort((c1, c2) => {
|
192 | return c1.colspanIndex - c2.colspanIndex
|
193 | })
|
194 |
|
195 | for (let j = 0; j < columns.length; j++) {
|
196 | if (columns[j].colspanGroup > 0) continue
|
197 |
|
198 | let rowspan = 0
|
199 | let colspan = 0
|
200 |
|
201 | if (this.mergedCells) {
|
202 | for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
203 | const currentMergedCell = this.mergedCells[mc]
|
204 |
|
205 | if (currentMergedCell.col === j && currentMergedCell.row === i) {
|
206 | rowspan = currentMergedCell.rowspan
|
207 | colspan = currentMergedCell.colspan
|
208 | }
|
209 | }
|
210 | }
|
211 |
|
212 | if (
|
213 | !columns[j].printIgnore && columns[j].visible && columns[j].field &&
|
214 | (
|
215 | !dontRender.includes(`${i},${j}`) ||
|
216 | rowspan > 0 && colspan > 0
|
217 | )
|
218 | ) {
|
219 | if (rowspan > 0 && colspan > 0) {
|
220 | html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>')
|
221 | } else {
|
222 | html.push('<td>', formatValue(data[i], i, columns[j]), '</td>')
|
223 | }
|
224 | }
|
225 | }
|
226 |
|
227 |
|
228 | html.push('</tr>')
|
229 | }
|
230 |
|
231 | html.push('</tbody>')
|
232 | if (this.options.showFooter) {
|
233 | html.push('<footer><tr>')
|
234 |
|
235 | for (const columns of columnsArray) {
|
236 | for (let h = 0; h < columns.length; h++) {
|
237 | if (!columns[h].printIgnore && columns[h].visible) {
|
238 | const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr'))
|
239 | const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '')
|
240 |
|
241 | html.push(`<th>${footerValue}</th>`)
|
242 | }
|
243 | }
|
244 | }
|
245 |
|
246 | html.push('</tr></footer>')
|
247 | }
|
248 | html.push('</table>')
|
249 | return html.join('')
|
250 | }
|
251 |
|
252 | const sortRows = (data, colName, sortOrder) => {
|
253 | if (!colName) {
|
254 | return data
|
255 | }
|
256 | let reverse = sortOrder !== 'asc'
|
257 |
|
258 | reverse = -(+reverse || -1)
|
259 | return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName]))
|
260 | }
|
261 |
|
262 | const filterRow = (row, filters) => {
|
263 | for (let index = 0; index < filters.length; ++index) {
|
264 | if (row[filters[index].colName] !== filters[index].value) {
|
265 | return false
|
266 | }
|
267 | }
|
268 | return true
|
269 | }
|
270 |
|
271 | const filterRows = (data, filters) => data.filter(row => filterRow(row, filters))
|
272 | const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
|
273 | colName: col.field,
|
274 | value: col.printFilter
|
275 | }))
|
276 |
|
277 | data = filterRows(data, getColumnFilters(this.options.columns))
|
278 | data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
|
279 | const table = buildTable(data, this.options.columns)
|
280 | const newWin = window.open('')
|
281 |
|
282 | const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder, [table], printPageBuilderDefault(table))
|
283 |
|
284 | newWin.document.write(calculatedPrintPage)
|
285 | newWin.document.close()
|
286 | newWin.focus()
|
287 | newWin.print()
|
288 | newWin.close()
|
289 | }
|
290 | }
|