print.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. interface PrintFunction {
  2. extendOptions: Function;
  3. getStyle: Function;
  4. setDomHeight: Function;
  5. toPrint: Function;
  6. }
  7. const Print = function (dom, options?: object): PrintFunction {
  8. options = options || {};
  9. // @ts-expect-error
  10. if (!(this instanceof Print)) return new Print(dom, options);
  11. this.conf = {
  12. styleStr: "",
  13. // Elements that need to dynamically get and set the height
  14. setDomHeightArr: [],
  15. // Echart dom List
  16. echartDomArr: [],
  17. // Callback before printing
  18. printBeforeFn: null,
  19. // Callback after printing
  20. printDoneCallBack: null
  21. };
  22. for (const key in this.conf) {
  23. // eslint-disable-next-line no-prototype-builtins
  24. if (key && options.hasOwnProperty(key)) {
  25. this.conf[key] = options[key];
  26. }
  27. }
  28. if (typeof dom === "string") {
  29. this.dom = document.querySelector(dom);
  30. } else {
  31. this.dom = this.isDOM(dom) ? dom : dom.$el;
  32. }
  33. if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) {
  34. this.setDomHeight(this.conf.setDomHeightArr);
  35. }
  36. this.init();
  37. };
  38. Print.prototype = {
  39. /**
  40. * init
  41. */
  42. init: function (): void {
  43. const content = this.getStyle() + this.getHtml();
  44. this.writeIframe(content);
  45. },
  46. /**
  47. * Configuration property extension
  48. * @param {Object} obj
  49. * @param {Object} obj2
  50. */
  51. extendOptions: function <T>(obj, obj2: T): T {
  52. for (const k in obj2) {
  53. obj[k] = obj2[k];
  54. }
  55. return obj;
  56. },
  57. /**
  58. Copy all styles of the original page
  59. */
  60. getStyle: function (): string {
  61. let str = "";
  62. const styles: NodeListOf<Element> = document.querySelectorAll("style,link");
  63. for (let i = 0; i < styles.length; i++) {
  64. str += styles[i].outerHTML;
  65. }
  66. str += `<style>.no-print{display:none;}${this.conf.styleStr}</style>`;
  67. return str;
  68. },
  69. // form assignment
  70. getHtml: function (): Element {
  71. const inputs = document.querySelectorAll("input");
  72. const selects = document.querySelectorAll("select");
  73. const textareas = document.querySelectorAll("textarea");
  74. for (let k = 0; k < inputs.length; k++) {
  75. if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
  76. if (inputs[k].checked == true) {
  77. inputs[k].setAttribute("checked", "checked");
  78. } else {
  79. inputs[k].removeAttribute("checked");
  80. }
  81. } else if (inputs[k].type == "text") {
  82. inputs[k].setAttribute("value", inputs[k].value);
  83. } else {
  84. inputs[k].setAttribute("value", inputs[k].value);
  85. }
  86. }
  87. for (let k2 = 0; k2 < textareas.length; k2++) {
  88. if (textareas[k2].type == "textarea") {
  89. textareas[k2].innerHTML = textareas[k2].value;
  90. }
  91. }
  92. for (let k3 = 0; k3 < selects.length; k3++) {
  93. if (selects[k3].type == "select-one") {
  94. const child = selects[k3].children;
  95. for (const i in child) {
  96. if (child[i].tagName == "OPTION") {
  97. if ((child[i] as any).selected == true) {
  98. child[i].setAttribute("selected", "selected");
  99. } else {
  100. child[i].removeAttribute("selected");
  101. }
  102. }
  103. }
  104. }
  105. }
  106. return this.dom.outerHTML;
  107. },
  108. /**
  109. create iframe
  110. */
  111. writeIframe: function (content) {
  112. let w: Document | Window;
  113. let doc: Document;
  114. const iframe: HTMLIFrameElement = document.createElement("iframe");
  115. const f: HTMLIFrameElement = document.body.appendChild(iframe);
  116. iframe.id = "myIframe";
  117. iframe.setAttribute(
  118. "style",
  119. "position:absolute;width:0;height:0;top:-10px;left:-10px;"
  120. );
  121. // eslint-disable-next-line prefer-const
  122. w = f.contentWindow || f.contentDocument;
  123. // eslint-disable-next-line prefer-const
  124. doc = f.contentDocument || f.contentWindow.document;
  125. doc.open();
  126. doc.write(content);
  127. doc.close();
  128. // eslint-disable-next-line @typescript-eslint/no-this-alias
  129. const _this = this;
  130. iframe.onload = function (): void {
  131. // Before popping, callback
  132. if (_this.conf.printBeforeFn) {
  133. _this.conf.printBeforeFn({ doc });
  134. }
  135. _this.drawEchartImg(doc).then(() => {
  136. _this.toPrint(w);
  137. setTimeout(function () {
  138. document.body.removeChild(iframe);
  139. // After popup, callback
  140. if (_this.conf.printDoneCallBack) {
  141. _this.conf.printDoneCallBack();
  142. }
  143. }, 100);
  144. });
  145. };
  146. },
  147. /**
  148. * echarts printing
  149. * @param {Object} doc iframe window
  150. */
  151. drawEchartImg(doc): Promise<void> {
  152. return new Promise<void>(resolve => {
  153. if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) {
  154. this.conf.echartDomArr.forEach(e => {
  155. const dom = doc.querySelector("#" + e.$el.id);
  156. const img = new Image();
  157. const w = dom.offsetWidth + "px";
  158. const H = dom.offsetHeight + "px";
  159. img.style.width = w;
  160. img.style.height = H;
  161. img.src = e.imgSrc;
  162. dom.innerHTML = "";
  163. dom.appendChild(img);
  164. });
  165. }
  166. resolve();
  167. });
  168. },
  169. /**
  170. Print
  171. */
  172. toPrint: function (frameWindow): void {
  173. try {
  174. setTimeout(function () {
  175. frameWindow.focus();
  176. try {
  177. if (!frameWindow.document.execCommand("print", false, null)) {
  178. frameWindow.print();
  179. }
  180. } catch (e) {
  181. frameWindow.print();
  182. }
  183. frameWindow.close();
  184. }, 10);
  185. } catch (err) {
  186. console.error(err);
  187. }
  188. },
  189. isDOM:
  190. typeof HTMLElement === "object"
  191. ? function (obj) {
  192. return obj instanceof HTMLElement;
  193. }
  194. : function (obj) {
  195. return (
  196. obj &&
  197. typeof obj === "object" &&
  198. obj.nodeType === 1 &&
  199. typeof obj.nodeName === "string"
  200. );
  201. },
  202. /**
  203. * Set the height of the specified dom element by getting the existing height of the dom element and setting
  204. * @param {Array} arr
  205. */
  206. setDomHeight(arr) {
  207. if (arr && arr.length) {
  208. arr.forEach(name => {
  209. const domArr = document.querySelectorAll(name);
  210. domArr.forEach(dom => {
  211. dom.style.height = dom.offsetHeight + "px";
  212. });
  213. });
  214. }
  215. }
  216. };
  217. export default Print;