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; } }