@cocreate/print 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +1 -1
- package/README.md +14 -0
- package/package.json +5 -5
- package/src/index.js +150 -153
package/CONTRIBUTING.md
CHANGED
|
@@ -13,7 +13,7 @@ Fork the [project on Github](https://github.com/CoCreate-app/CoCreate-print) and
|
|
|
13
13
|
```
|
|
14
14
|
git clone https://github.com/contributor/CoCreate-print.git
|
|
15
15
|
cd CoCreate-print
|
|
16
|
-
git remote add upstream https://
|
|
16
|
+
git remote add upstream https://gitlab.com/cocreatejs/CoCreate-print.git
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Create a Topic Branch
|
package/README.md
CHANGED
|
@@ -78,6 +78,20 @@ We want this library to be community-driven, and CoCreate led. We need your help
|
|
|
78
78
|
|
|
79
79
|
We appreciate your continued support, thank you!
|
|
80
80
|
|
|
81
|
+
## Print actions
|
|
82
|
+
|
|
83
|
+
Use `actions="print"` with `print-query` to print selected elements. Without an
|
|
84
|
+
`actions` attribute, `print-query` also works as a standalone click control.
|
|
85
|
+
Repeated initialization does not attach duplicate click handlers.
|
|
86
|
+
|
|
87
|
+
Printing copies current input, checkbox, textarea, and select values into an
|
|
88
|
+
isolated iframe, loads the page styles and images, and expands scroll containers
|
|
89
|
+
without changing the live view. The `printed` event is emitted from the trigger
|
|
90
|
+
and bubbles after the browser's print dialog closes (`afterprint`); it does not
|
|
91
|
+
indicate that the user actually printed rather than cancelled. Action chains
|
|
92
|
+
continue at that point. Failures emit `printError` and abort the chain. The print
|
|
93
|
+
iframe is removed on completion or failure.
|
|
94
|
+
|
|
81
95
|
# License
|
|
82
96
|
|
|
83
97
|
[The MIT License (MIT)](https://github.com/CoCreate-app/CoCreate-print/blob/master/LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/print",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A simple print component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"print",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://
|
|
25
|
+
"url": "git+https://gitlab.com/cocreatejs/CoCreate-print.git"
|
|
26
26
|
},
|
|
27
27
|
"author": "CoCreate LLC",
|
|
28
28
|
"license": "MIT",
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@cocreate/actions": "^1.24.0",
|
|
40
40
|
"@cocreate/element-prototype": "^1.35.0",
|
|
41
|
-
"@cocreate/observer": "^1.
|
|
42
|
-
"@cocreate/utils": "^1.
|
|
41
|
+
"@cocreate/observer": "^1.23.0",
|
|
42
|
+
"@cocreate/utils": "^1.54.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@cocreate/webpack": "^1.
|
|
45
|
+
"@cocreate/webpack": "^1.9.0"
|
|
46
46
|
},
|
|
47
47
|
"allowScripts": {
|
|
48
48
|
"@cocreate/actions@1.21.4": true,
|
package/src/index.js
CHANGED
|
@@ -1,153 +1,150 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (C) 2020 CoCreate LLC and others.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* SPDX-License-Identifier: MIT
|
|
6
|
-
********************************************************************************/
|
|
7
|
-
|
|
8
|
-
import "@cocreate/element-prototype";
|
|
9
|
-
import { queryElements } from "@cocreate/utils";
|
|
10
|
-
import Actions from "@cocreate/actions";
|
|
11
|
-
import Observer from "@cocreate/observer";
|
|
12
|
-
|
|
13
|
-
const selector = "[print-query]";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
export default { init, print };
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2020 CoCreate LLC and others.
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* SPDX-License-Identifier: MIT
|
|
6
|
+
********************************************************************************/
|
|
7
|
+
|
|
8
|
+
import "@cocreate/element-prototype";
|
|
9
|
+
import { queryElements } from "@cocreate/utils";
|
|
10
|
+
import Actions from "@cocreate/actions";
|
|
11
|
+
import Observer from "@cocreate/observer";
|
|
12
|
+
|
|
13
|
+
const selector = "[print-query]";
|
|
14
|
+
const initialized = new WeakSet();
|
|
15
|
+
|
|
16
|
+
function init(element) {
|
|
17
|
+
const elements = !element ? document.querySelectorAll(selector)
|
|
18
|
+
: element instanceof Element ? [element] : element;
|
|
19
|
+
for (const target of elements) {
|
|
20
|
+
if (!target.matches(selector) || initialized.has(target)) continue;
|
|
21
|
+
initialized.add(target);
|
|
22
|
+
target.addEventListener("click", () => {
|
|
23
|
+
if (target.hasAttribute("actions")) return;
|
|
24
|
+
runPrint({ element: target });
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function cloneForPrint(target) {
|
|
30
|
+
const clone = target.cloneNode(true);
|
|
31
|
+
const originals = [target, ...target.querySelectorAll("*")];
|
|
32
|
+
const copies = [clone, ...clone.querySelectorAll("*")];
|
|
33
|
+
originals.forEach((original, index) => {
|
|
34
|
+
const copy = copies[index];
|
|
35
|
+
const style = getComputedStyle(original);
|
|
36
|
+
// Unclip scrollable layouts without showing intentionally hidden content.
|
|
37
|
+
if (/(auto|scroll|hidden|clip)/.test(`${style.overflowX} ${style.overflowY}`)) {
|
|
38
|
+
for (const [name, value] of Object.entries({ overflow: "visible", height: "auto", "max-height": "none", "min-height": "0" }))
|
|
39
|
+
copy.style.setProperty(name, value, "important");
|
|
40
|
+
}
|
|
41
|
+
if (style.position === "sticky") copy.style.setProperty("position", "static", "important");
|
|
42
|
+
if (original.matches("input")) {
|
|
43
|
+
if (original.type !== "file") copy.setAttribute("value", original.value);
|
|
44
|
+
copy.toggleAttribute("checked", original.checked);
|
|
45
|
+
copy.indeterminate = original.indeterminate;
|
|
46
|
+
} else if (original.matches("textarea")) copy.textContent = original.value;
|
|
47
|
+
else if (original.matches("option")) copy.toggleAttribute("selected", original.selected);
|
|
48
|
+
for (const attribute of [...copy.attributes]) {
|
|
49
|
+
if (attribute.name.startsWith("on")) copy.removeAttribute(attribute.name);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const style = getComputedStyle(target);
|
|
53
|
+
for (const property of style) {
|
|
54
|
+
if (property.startsWith("--")) clone.style.setProperty(property, style.getPropertyValue(property));
|
|
55
|
+
}
|
|
56
|
+
clone.querySelectorAll("script, iframe, object, embed, .simplebar-track, .simplebar-placeholder").forEach(node => node.remove());
|
|
57
|
+
return clone;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function print(elements) {
|
|
61
|
+
if (!elements) return;
|
|
62
|
+
const targets = elements instanceof Element ? [elements] : Array.from(elements);
|
|
63
|
+
if (!targets.length) return;
|
|
64
|
+
const iframe = document.createElement("iframe");
|
|
65
|
+
iframe.title = "Print preview";
|
|
66
|
+
iframe.setAttribute("aria-hidden", "true");
|
|
67
|
+
iframe.style.cssText = "position:fixed;left:-10000px;top:0;width:1000px;height:800px;border:0";
|
|
68
|
+
document.body.appendChild(iframe);
|
|
69
|
+
const frame = iframe.contentWindow;
|
|
70
|
+
const doc = iframe.contentDocument;
|
|
71
|
+
try {
|
|
72
|
+
doc.open();
|
|
73
|
+
doc.write("<!doctype html><html><head><title>Print</title></head><body></body></html>");
|
|
74
|
+
doc.close();
|
|
75
|
+
for (const attribute of document.documentElement.attributes)
|
|
76
|
+
doc.documentElement.setAttribute(attribute.name, attribute.value);
|
|
77
|
+
for (const attribute of document.body.attributes)
|
|
78
|
+
doc.body.setAttribute(attribute.name, attribute.value);
|
|
79
|
+
const base = doc.createElement("base");
|
|
80
|
+
base.href = document.baseURI;
|
|
81
|
+
doc.head.appendChild(base);
|
|
82
|
+
const loading = [];
|
|
83
|
+
for (const sheet of document.querySelectorAll('style, link[rel="stylesheet"]')) {
|
|
84
|
+
const copy = sheet.cloneNode(true);
|
|
85
|
+
if (copy.tagName === "LINK") {
|
|
86
|
+
loading.push(new Promise(resolve => {
|
|
87
|
+
copy.addEventListener("load", resolve, { once: true });
|
|
88
|
+
copy.addEventListener("error", resolve, { once: true });
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
doc.head.appendChild(copy);
|
|
92
|
+
}
|
|
93
|
+
const styles = doc.createElement("style");
|
|
94
|
+
styles.textContent = `
|
|
95
|
+
html, body { height: auto !important; overflow: visible !important; }
|
|
96
|
+
.simplebar-wrapper, .simplebar-mask, .simplebar-offset,
|
|
97
|
+
.simplebar-content-wrapper, .simplebar-content {
|
|
98
|
+
position: static !important; overflow: visible !important;
|
|
99
|
+
height: auto !important; max-height: none !important;
|
|
100
|
+
width: auto !important; margin: 0 !important; transform: none !important;
|
|
101
|
+
}
|
|
102
|
+
thead { display: table-header-group; }
|
|
103
|
+
tr, img { break-inside: avoid; }
|
|
104
|
+
`;
|
|
105
|
+
doc.head.appendChild(styles);
|
|
106
|
+
for (const target of targets) doc.body.appendChild(doc.adoptNode(cloneForPrint(target)));
|
|
107
|
+
for (const img of doc.images) {
|
|
108
|
+
img.loading = "eager";
|
|
109
|
+
if (!img.complete) loading.push(new Promise(resolve => {
|
|
110
|
+
img.addEventListener("load", resolve, { once: true });
|
|
111
|
+
img.addEventListener("error", resolve, { once: true });
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
await Promise.all(loading);
|
|
115
|
+
if (doc.fonts?.ready) await doc.fonts.ready;
|
|
116
|
+
await new Promise(resolve => frame.requestAnimationFrame(() => frame.requestAnimationFrame(resolve)));
|
|
117
|
+
await new Promise((resolve, reject) => {
|
|
118
|
+
frame.addEventListener("afterprint", resolve, { once: true });
|
|
119
|
+
try { frame.focus(); frame.print(); } catch (error) { reject(error); }
|
|
120
|
+
});
|
|
121
|
+
} finally {
|
|
122
|
+
iframe.remove();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function runPrint(action) {
|
|
127
|
+
try {
|
|
128
|
+
const elements = action.element.hasAttribute("print-query")
|
|
129
|
+
? queryElements({ element: action.element, prefix: "print" }) : [action.element];
|
|
130
|
+
await print(elements);
|
|
131
|
+
if (action.end) action.end();
|
|
132
|
+
else action.element.dispatchEvent(new CustomEvent("printed", { bubbles: true }));
|
|
133
|
+
} catch (error) {
|
|
134
|
+
action.abort?.();
|
|
135
|
+
action.element.dispatchEvent(new CustomEvent("printError", { bubbles: true, detail: { error } }));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
init();
|
|
140
|
+
Actions.init([{ name: "print", endEvent: "printed", callback: runPrint }]);
|
|
141
|
+
Observer.init({
|
|
142
|
+
name: "CoCreatePrintAddedNodes", types: ["addedNodes"], selector,
|
|
143
|
+
callback: mutation => init(mutation.target)
|
|
144
|
+
});
|
|
145
|
+
Observer.init({
|
|
146
|
+
name: "CoCreatePrintObserver", types: ["attributes"], attributeFilter: ["print-query"], selector,
|
|
147
|
+
callback: mutation => init(mutation.target)
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export default { init, print };
|