You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

87 lines
2.0 KiB

interface PageSize {
width: number
height: number
margin: number
}
const createIframe = () => {
const iframe = document.createElement('iframe')
iframe.style.width = '0'
iframe.style.height = '0'
iframe.style.position = 'absolute'
iframe.style.right = '0'
iframe.style.top = '0'
iframe.style.border = '0'
document.body.appendChild(iframe)
return iframe
}
const writeContent = (doc: Document, printNode: HTMLElement, size: PageSize) => {
const docType = '<!DOCTYPE html>'
let style = ''
const styleSheets = document.styleSheets
if (styleSheets) {
for (const styleSheet of styleSheets) {
if (!styleSheet.cssRules) continue
for (const rule of styleSheet.cssRules) {
style += rule.cssText
}
}
}
const { width, height, margin } = size
const head = `
<head>
<style type="text/css">
${style}
html, body {
height: auto;
overflow: auto;
}
@media print {
@page {
size: ${width + 2 * margin}px ${height + 2 * margin}px;
margin: ${margin}px;
}
}
</style>
</head>
`
const body = '<body>' + printNode.innerHTML + '</body>'
doc.open()
doc.write(`
${docType}
<html>
${head}
${body}
</html>
`)
doc.close()
}
export const print = (printNode: HTMLElement, size: PageSize) => {
const iframe = createIframe()
const iframeContentWindow = iframe.contentWindow
if (!iframe.contentDocument || !iframeContentWindow) return
writeContent(iframe.contentDocument, printNode, size)
const handleLoadIframe = () => {
iframeContentWindow.focus()
iframeContentWindow.print()
}
const handleAfterprint = () => {
iframe.removeEventListener('load', handleLoadIframe)
iframeContentWindow.removeEventListener('afterprint', handleAfterprint)
document.body.removeChild(iframe)
}
iframe.addEventListener('load', handleLoadIframe)
iframeContentWindow.addEventListener('afterprint', handleAfterprint)
}