123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- 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()}<html>${this.getHead()}${this.getBody()}</html>`);
- PADocument.close();
- }
- docType () {
- if (this.settings.standard === this.standards.html5) {
- return '<!DOCTYPE html>';
- }
- var transitional = this.settings.standard === this.standards.loose ? ' Transitional' : '';
- var dtd = this.settings.standard === this.standards.loose ? 'loose' : 'strict';
- return `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01${transitional}//EN" "http://www.w3.org/TR/html4/${dtd}.dtd">`;
- }
- 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 += `<link type="text/css" rel="stylesheet" href="${item.href}" >`;
- }
- });
- // 循环获取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 += `<link type="text/css" rel="stylesheet" href="${m}">`;
- });
- }
- return `<head><title>${this.settings.popTitle}</title>${extraHead}${links}<style type="text/css">${style}</style></head>`;
- }
- 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 '<body>' + htm + '</body>';
- }
- // 处理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;
- }
- }
|