diff options
-rw-r--r-- | pointless/viewer/presentation.js | 46 | ||||
-rw-r--r-- | pointless/viewer/screen.js | 56 | ||||
-rw-r--r-- | pointless/viewer/stage.js | 54 | ||||
-rw-r--r-- | pointless/viewer/viewer.css | 19 | ||||
-rw-r--r-- | pointless/viewer/viewer.js | 23 | ||||
-rw-r--r-- | viewer.html | 26 |
6 files changed, 224 insertions, 0 deletions
diff --git a/pointless/viewer/presentation.js b/pointless/viewer/presentation.js new file mode 100644 index 0000000..853d764 --- /dev/null +++ b/pointless/viewer/presentation.js | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * presentation.js | ||
3 | * Part of Pointless Viewer, a Beamer presentation viewer | ||
4 | * Copyright 2018 Pacien TRAN-GIRARD | ||
5 | * License: GNU GPL v3 | ||
6 | */ | ||
7 | |||
8 | "use strict"; | ||
9 | |||
10 | class Presentation { | ||
11 | constructor(pdf) { | ||
12 | this.pdf = pdf; | ||
13 | this.currentPageIndex = 1; | ||
14 | this.stage = this._setupStage(); | ||
15 | } | ||
16 | |||
17 | _setupStage() { | ||
18 | var self = this; | ||
19 | var onStageReadyCallback = function() { self._onStageReady(); }; | ||
20 | var onNextCallback = function() { self._onNext(); }; | ||
21 | var onPreviousCallback = function() { self._onPrevious(); }; | ||
22 | return new Stage(onStageReadyCallback, onNextCallback, onPreviousCallback); | ||
23 | } | ||
24 | |||
25 | _onStageReady() { | ||
26 | this._setPage(this.currentPageIndex); | ||
27 | } | ||
28 | |||
29 | _onNext() { | ||
30 | if (this.currentPageIndex === this.pdf.numPages) return; | ||
31 | this._setPage(this.currentPageIndex + 1); | ||
32 | } | ||
33 | |||
34 | _onPrevious() { | ||
35 | if (this.currentPageIndex === 1) return; | ||
36 | this._setPage(this.currentPageIndex - 1); | ||
37 | } | ||
38 | |||
39 | _setPage(pageIndex) { | ||
40 | var self = this; | ||
41 | this.currentPageIndex = pageIndex; | ||
42 | this.pdf.getPage(this.currentPageIndex).then(function(page) { | ||
43 | self.stage.setPage(page); | ||
44 | }) | ||
45 | } | ||
46 | } | ||
diff --git a/pointless/viewer/screen.js b/pointless/viewer/screen.js new file mode 100644 index 0000000..8a6891c --- /dev/null +++ b/pointless/viewer/screen.js | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * screen.js | ||
3 | * Part of Pointless Viewer, a Beamer presentation viewer | ||
4 | * Copyright 2018 Pacien TRAN-GIRARD | ||
5 | * License: GNU GPL v3 | ||
6 | */ | ||
7 | |||
8 | "use strict"; | ||
9 | |||
10 | class Screen { | ||
11 | constructor(window, secondary=false) { | ||
12 | this.window = window; | ||
13 | this.secondary = secondary; | ||
14 | this.canvas = window.document.getElementById("screen"); | ||
15 | this.context = this.canvas.getContext("2d"); | ||
16 | this.page = null; | ||
17 | |||
18 | var self = this; | ||
19 | this.window.addEventListener("resize", function() { | ||
20 | self._refreshPage(); | ||
21 | }); | ||
22 | } | ||
23 | |||
24 | setPage(page) { | ||
25 | this.page = page; | ||
26 | this._refreshPage(); | ||
27 | } | ||
28 | |||
29 | _resizeScreen(ratio) { | ||
30 | var windowRatio = this.window.innerWidth / this.window.innerHeight; | ||
31 | var scaleFactor = ratio / windowRatio; | ||
32 | this.canvas.width = this.window.innerWidth * Math.min(scaleFactor, 1); | ||
33 | this.canvas.height = this.window.innerHeight / Math.max(scaleFactor, 1); | ||
34 | } | ||
35 | |||
36 | _setOffset() { | ||
37 | var xOffset = this.secondary ? -this.canvas.width : 0; | ||
38 | this.context.transform(1, 0, 0, 1, xOffset, 0); | ||
39 | } | ||
40 | |||
41 | _paintPage() { | ||
42 | var renderRatio = this.canvas.height / this.page.getViewport(1).height; | ||
43 | var renderViewport = this.page.getViewport(renderRatio); | ||
44 | var renderContext = { canvasContext: this.context, viewport: renderViewport }; | ||
45 | this.page.render(renderContext); | ||
46 | } | ||
47 | |||
48 | _refreshPage() { | ||
49 | if (this.page == null) return; | ||
50 | var viewport = this.page.getViewport(1); | ||
51 | var ratio = (viewport.width / 2) / viewport.height; | ||
52 | this._resizeScreen(ratio); | ||
53 | this._setOffset(); | ||
54 | this._paintPage(); | ||
55 | } | ||
56 | } | ||
diff --git a/pointless/viewer/stage.js b/pointless/viewer/stage.js new file mode 100644 index 0000000..fa984fe --- /dev/null +++ b/pointless/viewer/stage.js | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * stage.js | ||
3 | * Part of Pointless Viewer, a Beamer presentation viewer | ||
4 | * Copyright 2018 Pacien TRAN-GIRARD | ||
5 | * License: GNU GPL v3 | ||
6 | */ | ||
7 | |||
8 | "use strict"; | ||
9 | |||
10 | class Stage { | ||
11 | constructor(onReady, onNext, onPrevious) { | ||
12 | this.onNext = onNext; | ||
13 | this.onPrevious = onPrevious; | ||
14 | this.projector = window.open(window.location.href); | ||
15 | this.audienceScreen = null; | ||
16 | this.presenterScreen = null; | ||
17 | |||
18 | var self = this; | ||
19 | this.projector.addEventListener("load", function() { | ||
20 | self.audienceScreen = new Screen(self.projector, false); | ||
21 | self.presenterScreen = new Screen(window, true); | ||
22 | onReady(); | ||
23 | }); | ||
24 | |||
25 | this._registerEventHandler(window); | ||
26 | this._registerEventHandler(this.projector); | ||
27 | } | ||
28 | |||
29 | setPage(page) { | ||
30 | this.audienceScreen.setPage(page); | ||
31 | this.presenterScreen.setPage(page); | ||
32 | } | ||
33 | |||
34 | _registerEventHandler(window) { | ||
35 | var self = this; | ||
36 | window.addEventListener("keypress", function(event) { | ||
37 | self._onCommand(event); | ||
38 | }) | ||
39 | } | ||
40 | |||
41 | _onCommand(keyboardEvent) { | ||
42 | switch (keyboardEvent.key) { | ||
43 | case "Enter": | ||
44 | case " ": | ||
45 | case "ArrowRight": | ||
46 | case "n": | ||
47 | return this.onNext(); | ||
48 | |||
49 | case "ArrowLeft": | ||
50 | case "p": | ||
51 | return this.onPrevious(); | ||
52 | } | ||
53 | } | ||
54 | } | ||
diff --git a/pointless/viewer/viewer.css b/pointless/viewer/viewer.css new file mode 100644 index 0000000..dee9802 --- /dev/null +++ b/pointless/viewer/viewer.css | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * viewer.css | ||
3 | * Part of Pointless Viewer, a Beamer presentation viewer | ||
4 | * Copyright 2018 Pacien TRAN-GIRARD | ||
5 | * License: GNU GPL v3 | ||
6 | */ | ||
7 | |||
8 | body { | ||
9 | background-color: black; | ||
10 | color: white; | ||
11 | overflow: hidden; | ||
12 | } | ||
13 | |||
14 | #screen { | ||
15 | position: absolute; | ||
16 | top: 50%; | ||
17 | left: 50%; | ||
18 | transform: translateX(-50%) translateY(-50%); | ||
19 | } | ||
diff --git a/pointless/viewer/viewer.js b/pointless/viewer/viewer.js new file mode 100644 index 0000000..00c6f76 --- /dev/null +++ b/pointless/viewer/viewer.js | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * viewer.js | ||
3 | * Part of Pointless Viewer, a Beamer presentation viewer | ||
4 | * Copyright 2018 Pacien TRAN-GIRARD | ||
5 | * License: GNU GPL v3 | ||
6 | */ | ||
7 | |||
8 | "use strict"; | ||
9 | |||
10 | var params = function() { | ||
11 | var queryDict = {}; | ||
12 | location.search.substr(1).split("&").forEach(function(item) { | ||
13 | var pair = item.split("="); | ||
14 | queryDict[pair[0]] = pair[1]; | ||
15 | }); | ||
16 | return queryDict; | ||
17 | }(); | ||
18 | |||
19 | if (window.opener == null) { | ||
20 | pdfjsLib.getDocument(params["file"]).then(function(pdf) { | ||
21 | var presentation = new Presentation(pdf); | ||
22 | }); | ||
23 | } | ||
diff --git a/viewer.html b/viewer.html new file mode 100644 index 0000000..88e4f2e --- /dev/null +++ b/viewer.html | |||
@@ -0,0 +1,26 @@ | |||
1 | <!doctype html> | ||
2 | |||
3 | <!-- | ||
4 | viewer.html | ||
5 | Part of Pointless Viewer, a Beamer presentation viewer | ||
6 | Copyright 2018 Pacien TRAN-GIRARD | ||
7 | License: GNU GPL v3 | ||
8 | --> | ||
9 | |||
10 | <html> | ||
11 | <head> | ||
12 | <meta charset="utf-8"> | ||
13 | <link rel="stylesheet" type="text/css" href="pointless/viewer/viewer.css"> | ||
14 | <title>Pointless Viewer</title> | ||
15 | </head> | ||
16 | |||
17 | <body> | ||
18 | <canvas id="screen"></canvas> | ||
19 | |||
20 | <script type="text/javascript" src="pointless/pdfjs/pdf.js"></script> | ||
21 | <script type="text/javascript" src="pointless/viewer/screen.js"></script> | ||
22 | <script type="text/javascript" src="pointless/viewer/stage.js"></script> | ||
23 | <script type="text/javascript" src="pointless/viewer/presentation.js"></script> | ||
24 | <script type="text/javascript" src="pointless/viewer/viewer.js"></script> | ||
25 | </body> | ||
26 | </html> | ||