const isIE = () =>{
if (!!window.ActiveXobject || "ActiveXObject" in window) {
return true;
} else {
return false;
}
}
/**
* 判断是否是IE11
* @returns boolean
*/
const isIE11 = () => {
if((/Trident\/7\./).test(navigator.userAgent)) {
return true;
} else {
return false;
}
}
const isRemove = (dom) => {
if (isIE() || isIE11()) {
dom.removeNode(true)
} else {
dom.remove()
}
return dom
}
export default class {
constructor(option) {
this.standards = {
strict: 'strict',
loose: 'loose',
html5: 'html5'
};
this.previewBody = null;
this.close = null;
this.previewBodyUtilPrintBtn = null;
this.selectArray = []; // 存储select的
this.counter = 0;
this.settings = {
standard: this.standards.html5,
};
Object.assign(this.settings, option);
this.init();
}
init () {
this.counter++;
this.settings.id = `printArea_${this.counter}`;
let url = ''
if (this.settings.url && !this.settings.asyncUrl) {
url = this.settings.url
}
let _this = this
// 如果是异步的
if (this.settings.asyncUrl) {
_this.settings.asyncUrl(function (url) {
let PrintAreaWindow = _this.getPrintWindow(url); // 创建iframe
if (_this.settings.preview) {
// 打开预览弹窗
_this.previewIfrmaeLoad()
} else {
// 直接打印
_this.print(PrintAreaWindow);
}
}, _this.settings.vue)
return
}
let PrintAreaWindow = this.getPrintWindow(url); // 创建iframe
if (!this.settings.url) {
this.write(PrintAreaWindow.doc); // 写入内容
}
if (this.settings.preview) {
// 打开预览弹窗
this.previewIfrmaeLoad()
} else {
// 直接打印
this.print(PrintAreaWindow);
}
}
addEvent (element, type, callback) {
if (element.addEventListener) {
element.addEventListener(type, callback, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, callback);
} else {
element['on' + type] = callback;
}
}
previewIfrmaeLoad () {
let box = document.getElementById('vue-pirnt-nb-previewBox')
if (box) {
let _this = this
let iframe = box.querySelector('iframe')
this.settings.previewBeforeOpenCallback()
this.addEvent(iframe, 'load', function () {
_this.previewBoxShow()
_this.removeCanvasImg()
_this.settings.previewOpenCallback()
})
this.addEvent(box.querySelector('.previewBodyUtilPrintBtn'), 'click', function () {
_this.settings.beforeOpenCallback()
_this.settings.openCallback();
iframe.contentWindow.print();
_this.settings.closeCallback()
})
}
}
// 删除所有canva转换的图片
removeCanvasImg () {
let _this = this
try {
if (_this.elsdom) {
// 删除canva转变图片的dom节点
let canvasList = _this.elsdom.querySelectorAll('.canvasImg')
for (let i = 0; i < canvasList.length; i++) {
isRemove(canvasList[i])
}
}
} catch (e) {
console.log(e);
}
}
print (ifrmae) {
var _this = this;
let iframe = document.getElementById(this.settings.id) || ifrmae.f;
let iframeWin = document.getElementById(this.settings.id).contentWindow || ifrmae.f.contentWindow;
var _loaded = function () {
iframeWin.focus();
_this.settings.openCallback();
iframeWin.print();
isRemove(iframe)
_this.settings.closeCallback()
_this.removeCanvasImg()
}
_this.settings.beforeOpenCallback()
_this.addEvent(iframe, 'load', function () {
_loaded()
})
}
write (PADocument) {
PADocument.open();
PADocument.write(`${this.docType()}${this.getHead()}${this.getBody()}`);
PADocument.close();
}
docType () {
if (this.settings.standard === this.standards.html5) {
return '';
}
var transitional = this.settings.standard === this.standards.loose ? ' Transitional' : '';
var dtd = this.settings.standard === this.standards.loose ? 'loose' : 'strict';
return ``;
}
getHead () {
let extraHead = '';
let links = '';
let style = '';
if (this.settings.extraHead) {
this.settings.extraHead.replace(/([^,]+)/g, (m) => {
extraHead += m;
});
}
// 复制所有link标签
[].forEach.call(document.querySelectorAll('link'), function (item) {
if (item.href.indexOf('.css') >= 0) {
links += ``;
}
});
// 循环获取style标签的样式
let domStyle = document.styleSheets;
if (domStyle && domStyle.length > 0) {
for (let i = 0; i < domStyle.length; i++) {
try {
if (domStyle[i].cssRules || domStyle[i].rules) {
let rules = domStyle[i].cssRules || domStyle[i].rules;
for (let b = 0; b < rules.length; b++) {
style += rules[b].cssText;
}
}
} catch (e) {
console.log(domStyle[i].href + e);
}
}
}
if (this.settings.extraCss) {
this.settings.extraCss.replace(/([^,\s]+)/g, (m) => {
links += ``;
});
}
return `
${this.settings.popTitle}${extraHead}${links}`;
}
getBody () {
let ids = this.settings.ids;
ids = ids.replace(new RegExp("#", "g"), '');
this.elsdom = this.beforeHanler(document.getElementById(ids));
let ele = this.getFormData(this.elsdom);
let htm = ele.outerHTML;
return '' + htm + '';
}
// 处理canva转成图片
beforeHanler (elsdom) {
let canvasList = elsdom.querySelectorAll('canvas');
// canvas转换png图片
for (let i = 0; i < canvasList.length; i++) {
if (!canvasList[i].style.display) {
let _parent = canvasList[i].parentNode
let _canvasUrl = canvasList[i].toDataURL('image/png')
let _img = new Image()
_img.className = 'canvasImg'
_img.style.display = 'none'
_img.src = _canvasUrl
_parent.appendChild(_img)
}
}
return elsdom
}
// 根据type去处理form表单
getFormData (ele) {
let copy = ele.cloneNode(true);
let copiedInputs = copy.querySelectorAll('input,select,textarea');
let canvasImgList = copy.querySelectorAll('.canvasImg,canvas');
let selectCount = -1;
// 处理所有canvas
for (let i = 0; i < canvasImgList.length; i++) {
let _parent = canvasImgList[i].parentNode
let item = canvasImgList[i]
// 删除克隆后的canvas节点
if (item.tagName.toLowerCase() === 'canvas') {
_parent.removeChild(item)
} else {
item.style.display = 'block'
}
}
// 处理所有输入框
for (let i = 0; i < copiedInputs.length; i++) {
let item = copiedInputs[i];
let typeInput = item.getAttribute('type');
let copiedInput = copiedInputs[i];
// 获取select标签
if (!typeInput) {
typeInput = item.tagName === 'SELECT' ? 'select' : item.tagName === 'TEXTAREA' ? 'textarea' : '';
}
// 处理input框
if (item.tagName === 'INPUT') {
// 除了单选框 多选框比较特别
if (typeInput === 'radio' || typeInput === 'checkbox') {
if (item.checked) {
copiedInput.setAttribute('checked', item.checked);
}
} else {
copiedInput.value = item.value;
copiedInput.setAttribute('value', item.value);
}
// 处理select
} else if (typeInput === 'select') {
selectCount++;
for (let b = 0; b < ele.querySelectorAll('select').length; b++) {
let select = ele.querySelectorAll('select')[b]; // 获取原始层每一个select
!select.getAttribute('newbs') && select.setAttribute('newbs', b) // 添加标识
if (select.getAttribute('newbs') == selectCount) {
let opSelectedIndex = ele.querySelectorAll('select')[selectCount].selectedIndex;
item.options[opSelectedIndex].setAttribute('selected', true);
}
}
// 处理textarea
} else {
copiedInput.innerHTML = item.value;
copiedInput.setAttribute('html', item.value);
}
}
return copy;
}
getPrintWindow (url) {
var f = this.Iframe(url);
return {
f: f,
win: f.contentWindow || f,
doc: f.doc
};
}
previewBoxShow () {
let box = document.getElementById('vue-pirnt-nb-previewBox')
if (box) {
document.querySelector('html').setAttribute('style', 'overflow: hidden')
box.style.display = 'block'
}
}
previewBoxHide () {
let box = document.getElementById('vue-pirnt-nb-previewBox')
if (box) {
document.querySelector('html').setAttribute('style', 'overflow: visible;')
box.querySelector('iframe') && isRemove(box.querySelector('iframe'))
box.style.display = 'none'
}
}
previewBox () {
let box = document.getElementById('vue-pirnt-nb-previewBox')
let previewBodyClass = 'previewBody'
if (box) {
box.querySelector('iframe') && isRemove(box.querySelector('iframe'))
return {
close: box.querySelector('.previewClose'),
previewBody: box.querySelector(`.${previewBodyClass}`)
}
}
let previewContent = document.createElement('div');
previewContent.setAttribute('id', "vue-pirnt-nb-previewBox")
previewContent.setAttribute('style', 'position: fixed;top: 0px;left: 0px;width: 100%;height: 100%;background: white;display:none')
previewContent.style.zIndex = this.settings.zIndex
// 打印预览弹窗的header
let previewHeader = document.createElement('div');
previewHeader.setAttribute('class', "previewHeader")
previewHeader.setAttribute('style', "padding: 5px 20px;")
previewHeader.innerHTML = this.settings.previewTitle
previewContent.appendChild(previewHeader)
// close关闭按钮
this.close = document.createElement('div');
let close = this.close
close.setAttribute('class', "previewClose")
close.setAttribute('style', "position: absolute;top: 5px;right: 20px;width: 25px;height: 20px;cursor: pointer;")
let closeBefore = document.createElement('div');
let closeAfter = document.createElement('div');
closeBefore.setAttribute('class', "closeBefore")
closeBefore.setAttribute('style', "position: absolute;width: 3px;height: 100%;background: #040404;transform: rotate(45deg); top: 0px;left: 50%;")
closeAfter.setAttribute('class', "closeAfter")
closeAfter.setAttribute('style', "position: absolute;width: 3px;height: 100%;background: #040404;transform: rotate(-45deg); top: 0px;left: 50%;")
close.appendChild(closeBefore)
close.appendChild(closeAfter)
previewHeader.appendChild(close)
// 打印预览弹窗的body
this.previewBody = document.createElement('div');
let previewBody = this.previewBody
previewBody.setAttribute('class', previewBodyClass)
previewBody.setAttribute('style', "display: flex;flex-direction: column; height: 100%;")
previewContent.appendChild(previewBody)
// 打印预览弹窗的body的工具栏
let previewBodyUtil = document.createElement('div');
previewBodyUtil.setAttribute('class', "previewBodyUtil")
previewBodyUtil.setAttribute('style', "height: 32px;background: #474747;position: relative;")
previewBody.appendChild(previewBodyUtil)
// 打印的按钮
this.previewBodyUtilPrintBtn = document.createElement('div');
let previewBodyUtilPrintBtn = this.previewBodyUtilPrintBtn
previewBodyUtilPrintBtn.setAttribute('class', 'previewBodyUtilPrintBtn')
previewBodyUtilPrintBtn.innerHTML = this.settings.previewPrintBtnLabel
previewBodyUtilPrintBtn.setAttribute('style', 'position: absolute;padding: 2px 10px;margin-top: 3px;left: 24px;font-size: 14px;color: white;cursor: pointer;background-color: rgba(0,0,0,.12);background-image: linear-gradient(hsla(0,0%,100%,.05),hsla(0,0%,100%,0));background-clip: padding-box;border: 1px solid rgba(0,0,0,.35);border-color: rgba(0,0,0,.32) rgba(0,0,0,.38) rgba(0,0,0,.42);box-shadow: inset 0 1px 0 hsla(0,0%,100%,.05), inset 0 0 1px hsla(0,0%,100%,.15), 0 1px 0 hsla(0,0%,100%,.05);')
previewBodyUtil.appendChild(previewBodyUtilPrintBtn)
// 添加整个预览到body
document.body.appendChild(previewContent);
return {
close: this.close,
previewBody: this.previewBody
}
}
iframeBox (frameId, url) {
let iframe = document.createElement('iframe');
iframe.style.border = '0px';
iframe.style.position = 'absolute';
iframe.style.width = '0px';
iframe.style.height = '0px';
iframe.style.right = '0px';
iframe.style.top = '0px';
iframe.setAttribute('id', frameId);
iframe.setAttribute('src', url);
return iframe
}
Iframe (url) {
let frameId = this.settings.id;
// 局部打印 用当前的时间做ifrmae的url
url = !url ? new Date().getTime() : url
let _this = this
let iframe = this.iframeBox(frameId, url)
// let that = this
try {
// 直接打印 不预览
if (!this.settings.preview) {
document.body.appendChild(iframe);
} else {
iframe.setAttribute('style', 'border: 0px;flex: 1;')
// 预览打印
let previewBox = this.previewBox()
let previewBody = previewBox.previewBody
let close = previewBox.close
// 添加ifrmae到预览弹窗
previewBody.appendChild(iframe);
this.addEvent(close, 'click', function () {
_this.previewBoxHide()
})
}
iframe.doc = null;
iframe.doc = iframe.contentDocument ? iframe.contentDocument : (iframe.contentWindow ? iframe.contentWindow.document : iframe.document);
} catch (e) {
throw new Error(e + '. iframes may not be supported in this browser.');
}
if (iframe.doc == null) {
throw new Error('Cannot find document.');
}
return iframe;
}
}