src/controls/PrintButton.js
import $ from 'jquery'
import { Control } from './Control'
import { addTooltip } from '../html/html'
import { cssClasses } from '../globals'
import '../../less/printbutton.less'
export class PrintButton extends Control {
/**
* @param {g4uControlOptions} options
*/
constructor (options = {}) {
options.className = options.className || 'g4u-printbutton'
options.element = $('<button>').get(0)
super(options)
this.get$Element().addClass(this.className_)
.addClass(cssClasses.mainButton).html(this.getLocaliser().localiseUsingDictionary('PrintButton title'))
addTooltip(this.get$Element(), this.getLocaliser().localiseUsingDictionary('PrintButton tipLabel'))
this.get$Element().on('click', () => this.onClick_())
}
/**
* @private
*/
onClick_ () {
const setDivSize = function (div, mapSize) {
$(div).innerWidth(mapSize[0])
$(div).innerHeight(mapSize[1])
}
//
// Variant A: Create a new window and copy the canvas over there. This raises security issues in IE.
//
// Variant B: Apply a special css class to the body that hides everything except the map for @media print
// DOES NOT WORK
// -> doesn't work because hiding everything will hide the parents of the map, too
//
// Variant C: Create a new body and switching it with the old body for printing
// -> This heavily manipulates the existing DOM-Structure and it
// relies on the ol-viewport div being the only child of its parent.
// works in IE!
//
// Variant D: Convert everything to a pdf
// IMPLEMENTED IN MODULE
// -> jsPDF Print Module
//
// Variant E: Add a function to reproduce a map in its current state on another page
// NOT IMPLEMENTED
// -> some work, but maybe useful for other functions, too
//
const isMapCanvasTainted = function () { // Needs to be looked into
try {
const viewport = this.getMap().getViewport()
const srcCanvas = viewport.getElementsByTagName('canvas')[0]
srcCanvas.getContext('2d').getImageData(1, 1, 1, 1)
return false
} catch (e) {
return true
}
}
//
// We check if we can use variant a, if we cant, we use variant c
//
if (!isMapCanvasTainted()) {
//
// Variant A: Creating a new window and copying the canvas over there. This raises security issues in IE.
//
// new window
const newWindow = window.open('', '_blank')
const jStyleDiv = $('<div>').append(
$('style').clone()
).append(
$('link[type="text/css"]').clone()
)
// copying the map
const viewport = this.getMap().getViewport()
const mapClone = viewport.parentNode.cloneNode(true)
setDivSize(mapClone, this.getMap().getSize())
const srcCanvas = viewport.getElementsByTagName('canvas')[0]
const destCanvas = mapClone.getElementsByTagName('canvas')[0]
const destContext = destCanvas.getContext('2d')
destContext.drawImage(srcCanvas, 0, 0)
const newdoc = newWindow.document
// writing the document
newdoc.open()
newdoc.write('<!doctype html>')
newdoc.write('<html>')
newdoc.write('<head>')
newdoc.write('<title>')
newdoc.write(this.getLocaliser().localiseUsingDictionary('PrintButton windowTitle'))
newdoc.write('</title>')
newdoc.write(jStyleDiv.html())
newdoc.write('<script type="text/javascript">')
newdoc.write('window.onload = function () {\n')
newdoc.write('\twindow.focus();\n')
newdoc.write('\tsetTimeout( function () {\n') // we need to wait till the map is appended
newdoc.write('\t\twindow.print();\n')
newdoc.write('\t\twindow.close();\n')
newdoc.write('\t}, 50);\n')
newdoc.write('};')
newdoc.write('</script>')
newdoc.write('</head>')
newdoc.write('</html>')
newdoc.close()
newWindow.onload = function () {
newdoc.getElementsByTagName('body')[0].appendChild(mapClone)
}
newWindow.focus()
} else {
//
// Variant C: Creating a new body and switching it with the old body for printing
//
const $mapViewport = $(this.getMap().getViewport())
const $mapParent = $mapViewport.parent()
const $mapContainer = $mapParent.clone().empty().append($mapViewport)
setDivSize($mapContainer, this.getMap().getSize())
const $oldbody = $('body')
const $newbody = $('<body>').append($mapContainer)
document.body = $newbody.get(0)
window.print()
document.body = $oldbody.get(0)
$mapParent.append($mapViewport)
}
this.dispatchEvent('click')
}
}