UNPKG

7.04 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * Javascript code in this page
4 *
5 * Copyright 2021 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * Javascript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.XfaLayer = void 0;
28
29var _util = require("../shared/util.js");
30
31var _xfa_text = require("./xfa_text.js");
32
33class XfaLayer {
34 static setupStorage(html, id, element, storage, intent) {
35 const storedData = storage.getValue(id, {
36 value: null
37 });
38
39 switch (element.name) {
40 case "textarea":
41 if (storedData.value !== null) {
42 html.textContent = storedData.value;
43 }
44
45 if (intent === "print") {
46 break;
47 }
48
49 html.addEventListener("input", event => {
50 storage.setValue(id, {
51 value: event.target.value
52 });
53 });
54 break;
55
56 case "input":
57 if (element.attributes.type === "radio" || element.attributes.type === "checkbox") {
58 if (storedData.value === element.attributes.xfaOn) {
59 html.setAttribute("checked", true);
60 } else if (storedData.value === element.attributes.xfaOff) {
61 html.removeAttribute("checked");
62 }
63
64 if (intent === "print") {
65 break;
66 }
67
68 html.addEventListener("change", event => {
69 storage.setValue(id, {
70 value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff")
71 });
72 });
73 } else {
74 if (storedData.value !== null) {
75 html.setAttribute("value", storedData.value);
76 }
77
78 if (intent === "print") {
79 break;
80 }
81
82 html.addEventListener("input", event => {
83 storage.setValue(id, {
84 value: event.target.value
85 });
86 });
87 }
88
89 break;
90
91 case "select":
92 if (storedData.value !== null) {
93 for (const option of element.children) {
94 if (option.attributes.value === storedData.value) {
95 option.attributes.selected = true;
96 }
97 }
98 }
99
100 html.addEventListener("input", event => {
101 const options = event.target.options;
102 const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value;
103 storage.setValue(id, {
104 value
105 });
106 });
107 break;
108 }
109 }
110
111 static setAttributes({
112 html,
113 element,
114 storage = null,
115 intent,
116 linkService
117 }) {
118 const {
119 attributes
120 } = element;
121 const isHTMLAnchorElement = html instanceof HTMLAnchorElement;
122
123 if (attributes.type === "radio") {
124 attributes.name = `${attributes.name}-${intent}`;
125 }
126
127 for (const [key, value] of Object.entries(attributes)) {
128 if (value === null || value === undefined || key === "dataId") {
129 continue;
130 }
131
132 if (key !== "style") {
133 if (key === "textContent") {
134 html.textContent = value;
135 } else if (key === "class") {
136 if (value.length) {
137 html.setAttribute(key, value.join(" "));
138 }
139 } else {
140 if (isHTMLAnchorElement && (key === "href" || key === "newWindow")) {
141 continue;
142 }
143
144 html.setAttribute(key, value);
145 }
146 } else {
147 Object.assign(html.style, value);
148 }
149 }
150
151 if (isHTMLAnchorElement) {
152 if (!linkService.addLinkAttributes) {
153 (0, _util.warn)("XfaLayer.setAttribute - missing `addLinkAttributes`-method on the `linkService`-instance.");
154 }
155
156 linkService.addLinkAttributes?.(html, attributes.href, attributes.newWindow);
157 }
158
159 if (storage && attributes.dataId) {
160 this.setupStorage(html, attributes.dataId, element, storage);
161 }
162 }
163
164 static render(parameters) {
165 const storage = parameters.annotationStorage;
166 const linkService = parameters.linkService;
167 const root = parameters.xfaHtml;
168 const intent = parameters.intent || "display";
169 const rootHtml = document.createElement(root.name);
170
171 if (root.attributes) {
172 this.setAttributes({
173 html: rootHtml,
174 element: root,
175 intent,
176 linkService
177 });
178 }
179
180 const stack = [[root, -1, rootHtml]];
181 const rootDiv = parameters.div;
182 rootDiv.appendChild(rootHtml);
183
184 if (parameters.viewport) {
185 const transform = `matrix(${parameters.viewport.transform.join(",")})`;
186 rootDiv.style.transform = transform;
187 }
188
189 if (intent !== "richText") {
190 rootDiv.setAttribute("class", "xfaLayer xfaFont");
191 }
192
193 const textDivs = [];
194
195 while (stack.length > 0) {
196 const [parent, i, html] = stack[stack.length - 1];
197
198 if (i + 1 === parent.children.length) {
199 stack.pop();
200 continue;
201 }
202
203 const child = parent.children[++stack[stack.length - 1][1]];
204
205 if (child === null) {
206 continue;
207 }
208
209 const {
210 name
211 } = child;
212
213 if (name === "#text") {
214 const node = document.createTextNode(child.value);
215 textDivs.push(node);
216 html.appendChild(node);
217 continue;
218 }
219
220 let childHtml;
221
222 if (child?.attributes?.xmlns) {
223 childHtml = document.createElementNS(child.attributes.xmlns, name);
224 } else {
225 childHtml = document.createElement(name);
226 }
227
228 html.appendChild(childHtml);
229
230 if (child.attributes) {
231 this.setAttributes({
232 html: childHtml,
233 element: child,
234 storage,
235 intent,
236 linkService
237 });
238 }
239
240 if (child.children && child.children.length > 0) {
241 stack.push([child, -1, childHtml]);
242 } else if (child.value) {
243 const node = document.createTextNode(child.value);
244
245 if (_xfa_text.XfaText.shouldBuildText(name)) {
246 textDivs.push(node);
247 }
248
249 childHtml.appendChild(node);
250 }
251 }
252
253 for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) {
254 el.setAttribute("readOnly", true);
255 }
256
257 return {
258 textDivs
259 };
260 }
261
262 static update(parameters) {
263 const transform = `matrix(${parameters.viewport.transform.join(",")})`;
264 parameters.div.style.transform = transform;
265 parameters.div.hidden = false;
266 }
267
268}
269
270exports.XfaLayer = XfaLayer;
\No newline at end of file