UNPKG

10.2 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2022 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.PDFSidebar = void 0;
28
29var _ui_utils = require("./ui_utils.js");
30
31const UI_NOTIFICATION_CLASS = "pdfSidebarNotification";
32
33class PDFSidebar {
34 constructor({
35 elements,
36 pdfViewer,
37 pdfThumbnailViewer,
38 eventBus,
39 l10n
40 }) {
41 this.isOpen = false;
42 this.active = _ui_utils.SidebarView.THUMBS;
43 this.isInitialViewSet = false;
44 this.isInitialEventDispatched = false;
45 this.onToggled = null;
46 this.pdfViewer = pdfViewer;
47 this.pdfThumbnailViewer = pdfThumbnailViewer;
48 this.outerContainer = elements.outerContainer;
49 this.sidebarContainer = elements.sidebarContainer;
50 this.toggleButton = elements.toggleButton;
51 this.thumbnailButton = elements.thumbnailButton;
52 this.outlineButton = elements.outlineButton;
53 this.attachmentsButton = elements.attachmentsButton;
54 this.layersButton = elements.layersButton;
55 this.thumbnailView = elements.thumbnailView;
56 this.outlineView = elements.outlineView;
57 this.attachmentsView = elements.attachmentsView;
58 this.layersView = elements.layersView;
59 this._outlineOptionsContainer = elements.outlineOptionsContainer;
60 this._currentOutlineItemButton = elements.currentOutlineItemButton;
61 this.eventBus = eventBus;
62 this.l10n = l10n;
63 this.#addEventListeners();
64 }
65
66 reset() {
67 this.isInitialViewSet = false;
68 this.isInitialEventDispatched = false;
69 this.#hideUINotification(true);
70 this.switchView(_ui_utils.SidebarView.THUMBS);
71 this.outlineButton.disabled = false;
72 this.attachmentsButton.disabled = false;
73 this.layersButton.disabled = false;
74 this._currentOutlineItemButton.disabled = true;
75 }
76
77 get visibleView() {
78 return this.isOpen ? this.active : _ui_utils.SidebarView.NONE;
79 }
80
81 setInitialView(view = _ui_utils.SidebarView.NONE) {
82 if (this.isInitialViewSet) {
83 return;
84 }
85
86 this.isInitialViewSet = true;
87
88 if (view === _ui_utils.SidebarView.NONE || view === _ui_utils.SidebarView.UNKNOWN) {
89 this.#dispatchEvent();
90 return;
91 }
92
93 this.switchView(view, true);
94
95 if (!this.isInitialEventDispatched) {
96 this.#dispatchEvent();
97 }
98 }
99
100 switchView(view, forceOpen = false) {
101 const isViewChanged = view !== this.active;
102 let shouldForceRendering = false;
103
104 switch (view) {
105 case _ui_utils.SidebarView.NONE:
106 if (this.isOpen) {
107 this.close();
108 }
109
110 return;
111
112 case _ui_utils.SidebarView.THUMBS:
113 if (this.isOpen && isViewChanged) {
114 shouldForceRendering = true;
115 }
116
117 break;
118
119 case _ui_utils.SidebarView.OUTLINE:
120 if (this.outlineButton.disabled) {
121 return;
122 }
123
124 break;
125
126 case _ui_utils.SidebarView.ATTACHMENTS:
127 if (this.attachmentsButton.disabled) {
128 return;
129 }
130
131 break;
132
133 case _ui_utils.SidebarView.LAYERS:
134 if (this.layersButton.disabled) {
135 return;
136 }
137
138 break;
139
140 default:
141 console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`);
142 return;
143 }
144
145 this.active = view;
146 const isThumbs = view === _ui_utils.SidebarView.THUMBS,
147 isOutline = view === _ui_utils.SidebarView.OUTLINE,
148 isAttachments = view === _ui_utils.SidebarView.ATTACHMENTS,
149 isLayers = view === _ui_utils.SidebarView.LAYERS;
150 this.thumbnailButton.classList.toggle("toggled", isThumbs);
151 this.outlineButton.classList.toggle("toggled", isOutline);
152 this.attachmentsButton.classList.toggle("toggled", isAttachments);
153 this.layersButton.classList.toggle("toggled", isLayers);
154 this.thumbnailButton.setAttribute("aria-checked", isThumbs);
155 this.outlineButton.setAttribute("aria-checked", isOutline);
156 this.attachmentsButton.setAttribute("aria-checked", isAttachments);
157 this.layersButton.setAttribute("aria-checked", isLayers);
158 this.thumbnailView.classList.toggle("hidden", !isThumbs);
159 this.outlineView.classList.toggle("hidden", !isOutline);
160 this.attachmentsView.classList.toggle("hidden", !isAttachments);
161 this.layersView.classList.toggle("hidden", !isLayers);
162
163 this._outlineOptionsContainer.classList.toggle("hidden", !isOutline);
164
165 if (forceOpen && !this.isOpen) {
166 this.open();
167 return;
168 }
169
170 if (shouldForceRendering) {
171 this.#updateThumbnailViewer();
172 this.#forceRendering();
173 }
174
175 if (isViewChanged) {
176 this.#dispatchEvent();
177 }
178 }
179
180 open() {
181 if (this.isOpen) {
182 return;
183 }
184
185 this.isOpen = true;
186 this.toggleButton.classList.add("toggled");
187 this.toggleButton.setAttribute("aria-expanded", "true");
188 this.outerContainer.classList.add("sidebarMoving", "sidebarOpen");
189
190 if (this.active === _ui_utils.SidebarView.THUMBS) {
191 this.#updateThumbnailViewer();
192 }
193
194 this.#forceRendering();
195 this.#dispatchEvent();
196 this.#hideUINotification();
197 }
198
199 close() {
200 if (!this.isOpen) {
201 return;
202 }
203
204 this.isOpen = false;
205 this.toggleButton.classList.remove("toggled");
206 this.toggleButton.setAttribute("aria-expanded", "false");
207 this.outerContainer.classList.add("sidebarMoving");
208 this.outerContainer.classList.remove("sidebarOpen");
209 this.#forceRendering();
210 this.#dispatchEvent();
211 }
212
213 toggle() {
214 if (this.isOpen) {
215 this.close();
216 } else {
217 this.open();
218 }
219 }
220
221 #dispatchEvent() {
222 if (this.isInitialViewSet && !this.isInitialEventDispatched) {
223 this.isInitialEventDispatched = true;
224 }
225
226 this.eventBus.dispatch("sidebarviewchanged", {
227 source: this,
228 view: this.visibleView
229 });
230 }
231
232 #forceRendering() {
233 if (this.onToggled) {
234 this.onToggled();
235 } else {
236 this.pdfViewer.forceRendering();
237 this.pdfThumbnailViewer.forceRendering();
238 }
239 }
240
241 #updateThumbnailViewer() {
242 const {
243 pdfViewer,
244 pdfThumbnailViewer
245 } = this;
246 const pagesCount = pdfViewer.pagesCount;
247
248 for (let pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
249 const pageView = pdfViewer.getPageView(pageIndex);
250
251 if (pageView?.renderingState === _ui_utils.RenderingStates.FINISHED) {
252 const thumbnailView = pdfThumbnailViewer.getThumbnail(pageIndex);
253 thumbnailView.setImage(pageView);
254 }
255 }
256
257 pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
258 }
259
260 #showUINotification() {
261 this.l10n.get("toggle_sidebar_notification2.title").then(msg => {
262 this.toggleButton.title = msg;
263 });
264
265 if (!this.isOpen) {
266 this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);
267 }
268 }
269
270 #hideUINotification(reset = false) {
271 if (this.isOpen || reset) {
272 this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);
273 }
274
275 if (reset) {
276 this.l10n.get("toggle_sidebar.title").then(msg => {
277 this.toggleButton.title = msg;
278 });
279 }
280 }
281
282 #addEventListeners() {
283 this.sidebarContainer.addEventListener("transitionend", evt => {
284 if (evt.target === this.sidebarContainer) {
285 this.outerContainer.classList.remove("sidebarMoving");
286 }
287 });
288 this.toggleButton.addEventListener("click", () => {
289 this.toggle();
290 });
291 this.thumbnailButton.addEventListener("click", () => {
292 this.switchView(_ui_utils.SidebarView.THUMBS);
293 });
294 this.outlineButton.addEventListener("click", () => {
295 this.switchView(_ui_utils.SidebarView.OUTLINE);
296 });
297 this.outlineButton.addEventListener("dblclick", () => {
298 this.eventBus.dispatch("toggleoutlinetree", {
299 source: this
300 });
301 });
302 this.attachmentsButton.addEventListener("click", () => {
303 this.switchView(_ui_utils.SidebarView.ATTACHMENTS);
304 });
305 this.layersButton.addEventListener("click", () => {
306 this.switchView(_ui_utils.SidebarView.LAYERS);
307 });
308 this.layersButton.addEventListener("dblclick", () => {
309 this.eventBus.dispatch("resetlayers", {
310 source: this
311 });
312 });
313
314 this._currentOutlineItemButton.addEventListener("click", () => {
315 this.eventBus.dispatch("currentoutlineitem", {
316 source: this
317 });
318 });
319
320 const onTreeLoaded = (count, button, view) => {
321 button.disabled = !count;
322
323 if (count) {
324 this.#showUINotification();
325 } else if (this.active === view) {
326 this.switchView(_ui_utils.SidebarView.THUMBS);
327 }
328 };
329
330 this.eventBus._on("outlineloaded", evt => {
331 onTreeLoaded(evt.outlineCount, this.outlineButton, _ui_utils.SidebarView.OUTLINE);
332 evt.currentOutlineItemPromise.then(enabled => {
333 if (!this.isInitialViewSet) {
334 return;
335 }
336
337 this._currentOutlineItemButton.disabled = !enabled;
338 });
339 });
340
341 this.eventBus._on("attachmentsloaded", evt => {
342 onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, _ui_utils.SidebarView.ATTACHMENTS);
343 });
344
345 this.eventBus._on("layersloaded", evt => {
346 onTreeLoaded(evt.layersCount, this.layersButton, _ui_utils.SidebarView.LAYERS);
347 });
348
349 this.eventBus._on("presentationmodechanged", evt => {
350 if (evt.state === _ui_utils.PresentationModeState.NORMAL && this.visibleView === _ui_utils.SidebarView.THUMBS) {
351 this.#updateThumbnailViewer();
352 }
353 });
354 }
355
356}
357
358exports.PDFSidebar = PDFSidebar;
\No newline at end of file