print.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. // @ts-ignore
  98. if (child[i].selected == true) {
  99. child[i].setAttribute("selected", "selected");
  100. } else {
  101. child[i].removeAttribute("selected");
  102. }
  103. }
  104. }
  105. }
  106. }
  107. return this.dom.outerHTML;
  108. },
  109. /**
  110. create iframe
  111. */
  112. writeIframe: function (content) {
  113. let w: Document | Window;
  114. let doc: Document;
  115. const iframe: HTMLIFrameElement = document.createElement("iframe");
  116. const f: HTMLIFrameElement = document.body.appendChild(iframe);
  117. iframe.id = "myIframe";
  118. iframe.setAttribute(
  119. "style",
  120. "position:absolute;width:0;height:0;top:-10px;left:-10px;"
  121. );
  122. // eslint-disable-next-line prefer-const
  123. w = f.contentWindow || f.contentDocument;
  124. // eslint-disable-next-line prefer-const
  125. doc = f.contentDocument || f.contentWindow.document;
  126. doc.open();
  127. doc.write(content);
  128. doc.close();
  129. // eslint-disable-next-line @typescript-eslint/no-this-alias
  130. const _this = this;
  131. iframe.onload = function (): void {
  132. // Before popping, callback
  133. if (_this.conf.printBeforeFn) {
  134. _this.conf.printBeforeFn({ doc });
  135. }
  136. _this.drawEchartImg(doc).then(() => {
  137. _this.toPrint(w);
  138. setTimeout(function () {
  139. document.body.removeChild(iframe);
  140. // After popup, callback
  141. if (_this.conf.printDoneCallBack) {
  142. _this.conf.printDoneCallBack();
  143. }
  144. }, 100);
  145. });
  146. };
  147. },
  148. /**
  149. * echarts printing
  150. * @param {Object} doc iframe window
  151. */
  152. drawEchartImg(doc): Promise<void> {
  153. return new Promise<void>(resolve => {
  154. if (this.conf.echartDomArr && this.conf.echartDomArr.length > 0) {
  155. this.conf.echartDomArr.forEach(e => {
  156. const dom = doc.querySelector("#" + e.$el.id);
  157. const img = new Image();
  158. const w = dom.offsetWidth + "px";
  159. const H = dom.offsetHeight + "px";
  160. img.style.width = w;
  161. img.style.height = H;
  162. img.src = e.imgSrc;
  163. dom.innerHTML = "";
  164. dom.appendChild(img);
  165. });
  166. }
  167. resolve();
  168. });
  169. },
  170. /**
  171. Print
  172. */
  173. toPrint: function (frameWindow): void {
  174. try {
  175. setTimeout(function () {
  176. frameWindow.focus();
  177. try {
  178. if (!frameWindow.document.execCommand("print", false, null)) {
  179. frameWindow.print();
  180. }
  181. } catch (e) {
  182. frameWindow.print();
  183. }
  184. frameWindow.close();
  185. }, 10);
  186. } catch (err) {
  187. console.error(err);
  188. }
  189. },
  190. isDOM:
  191. typeof HTMLElement === "object"
  192. ? function (obj) {
  193. return obj instanceof HTMLElement;
  194. }
  195. : function (obj) {
  196. return (
  197. obj &&
  198. typeof obj === "object" &&
  199. obj.nodeType === 1 &&
  200. typeof obj.nodeName === "string"
  201. );
  202. },
  203. /**
  204. * Set the height of the specified dom element by getting the existing height of the dom element and setting
  205. * @param {Array} arr
  206. */
  207. setDomHeight(arr) {
  208. if (arr && arr.length) {
  209. arr.forEach(name => {
  210. const domArr = document.querySelectorAll(name);
  211. domArr.forEach(dom => {
  212. dom.style.height = dom.offsetHeight + "px";
  213. });
  214. });
  215. }
  216. }
  217. };
  218. export default Print;