diff options
Diffstat (limited to 'beamer/viewer')
-rw-r--r-- | beamer/viewer/init.js | 67 | ||||
-rw-r--r-- | beamer/viewer/presentation.js | 57 | ||||
-rw-r--r-- | beamer/viewer/screen/screen.js | 110 | ||||
-rw-r--r-- | beamer/viewer/screen/timer.js | 48 | ||||
-rw-r--r-- | beamer/viewer/stage/actions.js | 121 | ||||
-rw-r--r-- | beamer/viewer/stage/stage.js | 76 | ||||
-rw-r--r-- | beamer/viewer/viewer.css | 116 | ||||
-rw-r--r-- | beamer/viewer/viewer.js | 65 |
8 files changed, 660 insertions, 0 deletions
diff --git a/beamer/viewer/init.js b/beamer/viewer/init.js new file mode 100644 index 0000000..9192834 --- /dev/null +++ b/beamer/viewer/init.js | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Beamer Viewer, a web-based PDF presentation viewer | ||
3 | * Copyright (C) 2018 Pacien TRAN-GIRARD | ||
4 | * | ||
5 | * This program is free software: you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Affero General Public License as | ||
7 | * published by the Free Software Foundation, either version 3 of the | ||
8 | * License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | "use strict"; | ||
20 | |||
21 | const params = function() { | ||
22 | const queryDict = {}; | ||
23 | location.hash.substr(1).split("&").forEach(item => { | ||
24 | const pair = item.split("="); | ||
25 | queryDict[pair[0]] = pair[1]; | ||
26 | }); | ||
27 | return queryDict; | ||
28 | }(); | ||
29 | |||
30 | function isController() { | ||
31 | return window.opener == null || window.opener.location.href != window.location.href; | ||
32 | } | ||
33 | |||
34 | function initCache() { | ||
35 | if (!navigator.serviceWorker) return; | ||
36 | navigator.serviceWorker.register("appcache.js"); | ||
37 | |||
38 | const offlineCapableIndicator = document.getElementById("offlineCapable"); | ||
39 | offlineCapableIndicator.style.visibility = "visible"; | ||
40 | } | ||
41 | |||
42 | function checkPopupPermission() { | ||
43 | const popup = window.open("popup.html"); | ||
44 | |||
45 | if (popup == null) { | ||
46 | const warningMessage = document.getElementById("warning"); | ||
47 | warningMessage.textContent = "A pop-up blocker is active. Make sure to allow pop-ups on this website."; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | function init() { | ||
52 | initCache(); | ||
53 | checkPopupPermission(); | ||
54 | |||
55 | const viewer = new Viewer(); | ||
56 | |||
57 | if ("file" in params) | ||
58 | viewer.load(params["file"]); | ||
59 | } | ||
60 | |||
61 | function load(file) { | ||
62 | location.hash = "file=" + file; | ||
63 | location.reload(); | ||
64 | } | ||
65 | |||
66 | if (isController()) | ||
67 | init(); | ||
diff --git a/beamer/viewer/presentation.js b/beamer/viewer/presentation.js new file mode 100644 index 0000000..222a6d4 --- /dev/null +++ b/beamer/viewer/presentation.js | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Beamer Viewer, a web-based PDF presentation viewer | ||
3 | * Copyright (C) 2018 Pacien TRAN-GIRARD | ||
4 | * | ||
5 | * This program is free software: you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Affero General Public License as | ||
7 | * published by the Free Software Foundation, either version 3 of the | ||
8 | * License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | "use strict"; | ||
20 | |||
21 | class Presentation { | ||
22 | constructor(pdf) { | ||
23 | this.pdf = pdf; | ||
24 | this.currentPageIndex = 1; | ||
25 | this.stage = this._setupStage(); | ||
26 | } | ||
27 | |||
28 | _setupStage() { | ||
29 | const self = this; | ||
30 | const onStageReadyCallback = function() { self._onStageReady(); }; | ||
31 | const onNextCallback = function() { self._onNext(); }; | ||
32 | const onPreviousCallback = function() { self._onPrevious(); }; | ||
33 | return new Stage(onStageReadyCallback, onNextCallback, onPreviousCallback); | ||
34 | } | ||
35 | |||
36 | _onStageReady() { | ||
37 | this._setPage(this.currentPageIndex); | ||
38 | } | ||
39 | |||
40 | _onNext() { | ||
41 | if (this.currentPageIndex === this.pdf.numPages) return; | ||
42 | this._setPage(this.currentPageIndex + 1); | ||
43 | } | ||
44 | |||
45 | _onPrevious() { | ||
46 | if (this.currentPageIndex === 1) return; | ||
47 | this._setPage(this.currentPageIndex - 1); | ||
48 | } | ||
49 | |||
50 | _setPage(pageIndex) { | ||
51 | const self = this; | ||
52 | this.currentPageIndex = pageIndex; | ||
53 | this.pdf.getPage(this.currentPageIndex).then(function(page) { | ||
54 | self.stage.setPage(page); | ||
55 | }) | ||
56 | } | ||
57 | } | ||
diff --git a/beamer/viewer/screen/screen.js b/beamer/viewer/screen/screen.js new file mode 100644 index 0000000..c65ebc3 --- /dev/null +++ b/beamer/viewer/screen/screen.js | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Beamer Viewer, a web-based PDF presentation viewer | ||
3 | * Copyright (C) 2018 Pacien TRAN-GIRARD | ||
4 | * | ||
5 | * This program is free software: you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Affero General Public License as | ||
7 | * published by the Free Software Foundation, either version 3 of the | ||
8 | * License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | "use strict"; | ||
20 | |||
21 | class Screen { | ||
22 | constructor(window, secondary=false, withTimer=false) { | ||
23 | this.window = window; | ||
24 | this.secondary = secondary; | ||
25 | |||
26 | this.canvasId = "screen"; | ||
27 | this.page = null; | ||
28 | |||
29 | this.timer = withTimer ? new Timer(window) : null; | ||
30 | this.pageTurnCount = 0; | ||
31 | |||
32 | this._registerListeners(); | ||
33 | this._hideWelcomeScreen(); | ||
34 | } | ||
35 | |||
36 | setPage(page) { | ||
37 | if (this.pageTurnCount++ === 1 && this.timer != null) | ||
38 | this.timer.start(); | ||
39 | |||
40 | this.page = page; | ||
41 | this._repaint(); | ||
42 | } | ||
43 | |||
44 | _registerListeners() { | ||
45 | const self = this; | ||
46 | this.window.addEventListener("resize", function() { | ||
47 | self._repaint(); | ||
48 | }); | ||
49 | } | ||
50 | |||
51 | _hideWelcomeScreen() { | ||
52 | const welcomeScreen = this.window.document.getElementById("welcomeScreen"); | ||
53 | welcomeScreen.style.display = "none"; | ||
54 | } | ||
55 | |||
56 | _getScreenSize(ratio) { | ||
57 | const windowRatio = this.window.innerWidth / this.window.innerHeight; | ||
58 | const horizontalScaleFactor = ratio / windowRatio; | ||
59 | return { | ||
60 | width: this.window.innerWidth * Math.min(horizontalScaleFactor, 1), | ||
61 | height: this.window.innerHeight / Math.max(horizontalScaleFactor, 1) | ||
62 | }; | ||
63 | } | ||
64 | |||
65 | _getSlideSizeRatio() { | ||
66 | const viewport = this.page.getViewport(1); | ||
67 | return (viewport.width / 2) / viewport.height; | ||
68 | } | ||
69 | |||
70 | _newCanvas(width, height, xOffset, yOffset) { | ||
71 | const canvas = document.createElement("canvas"); | ||
72 | canvas.width = width; | ||
73 | canvas.height = height; | ||
74 | |||
75 | const context = canvas.getContext("2d"); | ||
76 | context.transform(1, 0, 0, 1, xOffset, yOffset); | ||
77 | |||
78 | return { canvas: canvas, context: context }; | ||
79 | } | ||
80 | |||
81 | _showCanvas(canvas) { | ||
82 | const oldCanvas = this.window.document.getElementById(this.canvasId); | ||
83 | canvas.id = oldCanvas.id; | ||
84 | canvas.classList = oldCanvas.classList; | ||
85 | oldCanvas.replaceWith(canvas); | ||
86 | } | ||
87 | |||
88 | _render(canvas, context, scaleFactor) { | ||
89 | const renderContext = { | ||
90 | canvasContext: context, | ||
91 | viewport: this.page.getViewport(scaleFactor) | ||
92 | }; | ||
93 | |||
94 | const self = this; | ||
95 | this.page.render(renderContext).then(function() { | ||
96 | self._showCanvas(canvas); | ||
97 | }); | ||
98 | } | ||
99 | |||
100 | _repaint() { | ||
101 | if (this.page == null) return; | ||
102 | |||
103 | const screenRatio = this._getSlideSizeRatio(); | ||
104 | const { width, height } = this._getScreenSize(screenRatio); | ||