Javascript网页打印局部区域(原生不依赖框架),带预览,继承CSS,可用于jQuery或vue等

2021-06-14 752点热度 0人点赞 0条评论

开发业务系统经常需要打印打印某个div(如打印业务系统生成的表单),而不是打印整个页面,这里分享我自用的工具代码,并不依赖框架,在原生Javascript下或者Vue下都能使用。

首先准备printArea.js,如下,保存成printArea.js,后面在html里引入js的时候用到。

/*
 * Copyright (c) 2021.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
            (global = global || self, (global.index = global.index || {}, global.index.js = factory()));
}(this, function () { 'use strict';

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    function _defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if ("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
        }
    }

    function _createClass(Constructor, protoProps, staticProps) {
        if (protoProps) _defineProperties(Constructor.prototype, protoProps);
        if (staticProps) _defineProperties(Constructor, staticProps);
        return Constructor;
    }

    var PrintArea =
        /*#__PURE__*/
        function () {
            function PrintArea(ele, options) {
                _classCallCheck(this, PrintArea);

                this.counter = 0;
                this.modes = {
                    iframe: "iframe",
                    popup: "popup"
                };
                this.standards = {
                    strict: "strict",
                    loose: "loose",
                    html5: "html5"
                };
                var defaults = {
                    mode: this.modes.iframe,
                    standard: this.standards.html5,
                    popHt: 500,
                    popWd: 400,
                    popX: 200,
                    popY: 200,
                    popTitle: '',
                    popClose: true,
                    extraCss: '',
                    extraHead: '',
                    retainAttr: ["id", "class", "style"]
                };
                this.settings = Object.assign({}, defaults, options);
                this.idPrefix = "printArea_";
                this.ele = ele.nodeType === 1 ? ele : document.querySelector(ele);
            }

            _createClass(PrintArea, [{
                key: "print",
                value: function print() {
                    var _this = this;

                    this.counter++;
                    var prefixList = document.querySelectorAll("[id^=" + this.idPrefix + "]");

                    while (prefixList.length) {
                        prefixList[0].parentNode.removeChild(prefixList[0]);
                        prefixList = document.querySelectorAll("[id^=" + this.idPrefix + "]");
                    }

                    this.settings.id = this.idPrefix + this.counter;
                    var PrintAreaWindow = this.getPrintWindow();
                    this.write(PrintAreaWindow.doc, this.ele);
                    setTimeout(function () {
                        _this.windowPrint(PrintAreaWindow);
                    }, 1000);
                }
            }, {
                key: "windowPrint",
                value: function windowPrint(PAWindow) {
                    var paWindow = PAWindow.win;
                    paWindow.focus();
                    paWindow.print();

                    if (this.settings.mode === this.modes.popup && this.settings.popClose) {
                        setTimeout(function () {
                            paWindow.close();
                        }, 1000);
                    }
                }
            }, {
                key: "write",
                value: function write(PADocument, element) {
                    PADocument.open();
                    PADocument.write(this.docType() + "<html>" + this.getHead() + this.getBody(element) + "</html>");
                    PADocument.close();
                }
            }, {
                key: "docType",
                value: function docType() {
                    if (this.settings.mode === this.modes.iframe) {
                        return "";
                    }

                    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">';
                }
            }, {
                key: "getHead",
                value: function getHead() {
                    var extraHead = "";

                    if (this.settings.extraHead) {
                        this.settings.extraHead.replace(/([^,]+)/g, function (m) {
                            extraHead += m;
                        });
                    }

                    var linkList = document.querySelectorAll('link');
                    linkList = Array.from(linkList).filter(function (item) {
                        var relAttr = item.getAttribute("rel");
                        return relAttr && relAttr.toLowerCase() === 'stylesheet';
                    }).filter(function (item) {
                        var mediaAttr = item.getAttribute("media");
                        return !mediaAttr || mediaAttr.toLowerCase() === 'print' || mediaAttr.toLowerCase() === 'all';
                    }).map(function (item) {
                        var href = item.getAttribute("href");
                        return "<link type=\"text/css\" rel=\"stylesheet\" href=\"".concat(href, "\" >");
                    });

                    if (this.settings.extraCss) {
                        this.settings.extraCss.replace(/([^,\s]+)/g, function (m) {
                            extraHead += '<link type="text/css" rel="stylesheet" href="' + m + '">';
                        });
                    }

                    return "<head><title>" + this.settings.popTitle + "</title>" + extraHead + linkList.join('\n') + "</head>";
                }
            }, {
                key: "getBody",
                value: function getBody(element) {
                    var html = "";
                    var attrs = this.settings.retainAttr;
                    var ele = this.getFormData(element);
                    var attributes = "";
                    attrs.forEach(function (attr) {
                        var eleAttr = ele.getAttribute(attr);

                        if (eleAttr) {
                            attributes += (attributes.length > 0 ? " " : "") + attr + "='" + eleAttr + "'";
                        }
                    });
                    html += '<div ' + attributes + '>' + ele.innerHTML + '</div>';
                    return "<body>" + html + "</body>";
                }
            }, {
                key: "getFormData",
                value: function getFormData(ele) {
                    var copy = ele.cloneNode(true);
                    var copiedInputs = copy.querySelectorAll("input,select,textarea");
                    Array.from(ele.querySelectorAll("input,select,textarea")).forEach(function (item, index) {
                        var typeInput = item.getAttribute("type");

                        if (!typeInput) {
                            var targetName = item.nodeName;
                            typeInput = targetName === 'SELECT' ? "select" : targetName === 'TEXTAREA' ? "textarea" : "";
                        }

                        var copiedInput = copiedInputs[index];

                        if (typeInput === "radio" || typeInput === "checkbox") {
                            copiedInput.removeAttribute('checked');

                            if (item.checked) {
                                copiedInput.setAttribute('checked', true);
                            }
                        } else if (typeInput === "text" || typeInput === "") {
                            copiedInput.setAttribute("value", item.textContent);
                        } else if (typeInput === "select") {
                            var options = item.querySelectorAll('option');
                            var copiedOptions = copiedInput.querySelectorAll('option');
                            Array.from(options).forEach(function (option, optionIndex) {
                                copiedOptions[optionIndex].removeAttribute('selected');

                                if (option.selected) {
                                    copiedOptions[optionIndex].setAttribute('selected', true);
                                }
                            });
                        } else if (typeInput === "textarea") {
                            copiedInput.textContent = item.value;
                        }
                    });
                    return copy;
                }
            }, {
                key: "getPrintWindow",
                value: function getPrintWindow() {
                    switch (this.settings.mode) {
                        case this.modes.iframe:
                            var f = this.Iframe();
                            return {
                                win: f.contentWindow || f,
                                doc: f.doc
                            };

                        case this.modes.popup:
                            var p = this.Popup();
                            return {
                                win: p,
                                doc: p.doc
                            };
                    }
                }
            }, {
                key: "Iframe",
                value: function Iframe() {
                    var frameId = this.settings.id;
                    var iframeStyle = 'border:0;position:absolute;width:0px;height:0px;right:0px;top:0px;';
                    var iframe;

                    try {
                        iframe = document.createElement('iframe');
                        document.body.appendChild(iframe);
                        iframe.setAttribute('style', iframeStyle);
                        iframe.setAttribute('id', frameId);
                        iframe.setAttribute('src', "#" + new Date().getTime());
                        iframe.doc = null;
                        iframe.doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow ? iframe.contentWindow.document : iframe.document;
                    } catch (e) {
                        throw e + ". iframes may not be supported in this browser.";
                    }

                    if (iframe.doc == null) throw "Cannot find document.";
                    return iframe;
                }
            }, {
                key: "Popup",
                value: function Popup() {
                    var windowAttr = "location=yes,statusbar=no,directories=no,menubar=no,titlebar=no,toolbar=no,dependent=no";
                    windowAttr += ",width=" + this.settings.popWd + ",height=" + this.settings.popHt;
                    windowAttr += ",resizable=yes,screenX=" + this.settings.popX + ",screenY=" + this.settings.popY + ",personalbar=no,scrollbars=yes";
                    var newWin = window.open("", "_blank", windowAttr);
                    newWin.doc = newWin.document;
                    return newWin;
                }
            }]);

            return PrintArea;
        }();
    window.PrintArea = PrintArea;

    return PrintArea;

}));

下面原生Html/JS下实现调用打印:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Untitled Document</title>

        <!-- 引入printArea.js -->
        <script type="text/javascript" src="printArea.js"></script>

        <!-- 可加载css,也可以使用@media print来指定特定在打印的时候才显示的样式
        <link rel="stylesheet" type="text/css" href="xxx.css"> -->

        @media print {
            /* 这里还可以将不需要打印出来的地方直接用display:none;隐藏。 */

            td, tr {
                page-break-inside: avoid;
            }
            /* 用于设置是否在指定元素中插入分页,avoid 避免在元素内部插入分页符。 */
        }
    </head>

    <body>
        <button onclick="print2()">打印</button>
        <!--    这里是需要局部打印的内容,不显示在网页上,只需要打印,所以display: none; -->
        <div style="display: none;">
            <div id="print2" style="width: 900px; margin:0 auto;color:black;font-family: SimHei,黑体,SimSun,serif;">
                <h4 style="text-align:center;">测试打印内容</div>
            </div>
        </div>

    <script type="text/javascript">
        function print2() {
            const printArea = new PrintArea(document.getElementById('print2'),{});
            printArea.print();
        }
    </script>
    </body>
</html>

怎么样,是不是很简单,总结下来,就是需要打印的时候,调用:

// new PrintArea第一个参数接收一个需要打印的区域,我们这里用id为print2来选取:document.getElementById('print2')
const printArea = new PrintArea(document.getElementById('print2'),{}); 
printArea.print();

需要打印的上层,用一个隐藏的div包起来,这样就不会显示在主页面上了。

如果需要在vue里调用呢?也很简单(这里使用到了$nextTick),html里面正常引入printArea.js,需要打印的区域也用div包起来,很上面纯html实现一样,最后调用打印的代码如下:

// vue下使用printArea.js打印
printClicked2: function() {
    var _this = this;
    _this.$nextTick(function () {
        const printArea = new PrintArea(document.getElementById('print2'),{});
        printArea.print();
    });
},

 

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论