1const DEFAULT_TITLE = "ppt-control";
2const LABEL_STOPPED = "Slideshow stopped";
3const LABEL_RUNNING = "Slideshow running";
4const LABEL_DISCONNECTED = "Disconnected";
5const LABEL_FINAL_PREFIX = "Final slide ‐ ";
6const LABEL_END_PREFIX = "End of slideshow ‐ ";
7var preloaded = false;
8var preload = [];
9
10var presentation = document.querySelector('#presentation'),
11 startBtn = document.querySelector('.start'),
12 stopBtn = document.querySelector('.stop'),
13 prev = document.querySelector('#prev'),
14 next = document.querySelector('#next'),
15 first = document.querySelector('#first'),
16 last = document.querySelector('#last'),
17 black = document.querySelector('#black'),
18 white = document.querySelector('#white'),
19 slide_label = document.querySelector('#slide_label'),
20 current = document.querySelector('#current'),
21 total = document.querySelector('#total'),
22 status_text = document.querySelector('.status_text'),
23 presentation_text = document.querySelector('.presentation_text'),
24 current_img = document.querySelector('#current_img'),
25 next_img = document.querySelector('#next_img'),
26 current_div = document.querySelector('#current_div'),
27 next_div = document.querySelector('#next_div'),
28 controls_container = document.querySelector('#controls_container'),
29 controls_container_inner = document.querySelector('#controls_container_inner'),
30 show_current = document.querySelector('#show_current'),
31 show_next = document.querySelector('#show_next'),
32 shortcuts = document.querySelector('#shortcuts');
33
34var presentationData = {};
35var presentationOptions = {};
36
37
38function getPresentationName() {
39 if (presentation.selectedOptions.length > 0) {
40 return presentation.selectedOptions[0].innerText;
41 } else {
42 return "";
43 }
44}
45
46
47function startWebsocket() {
48 console.log("Attempting to connect")
49 ws = new WebSocket("ws://" + window.location.host + ":5678/");
50 ws.onmessage = receive_message;
51 ws.onclose = function(){
52 ws = null;
53 setTimeout(function(){websocket = startWebsocket()}, 1000);
54 }
55 if (ws.readyState !== WebSocket.OPEN) {
56 disconnect()
57 }
58 return ws;
59}
60
61var websocket = startWebsocket();
62
63prev.onclick = function (event) {
64 if (getPresentationName()) {
65 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'prev'}));
66 }
67}
68
69next.onclick = function (event) {
70 if (getPresentationName()) {
71 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'next'}));
72 }
73}
74
75first.onclick = function (event) {
76 if (getPresentationName()) {
77 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'first'}));
78 }
79}
80
81last.onclick = function (event) {
82 if (getPresentationName()) {
83 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'last'}));
84 }
85}
86
87black.onclick = function (event) {
88 if (getPresentationName()) {
89 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'black'}));
90 }
91}
92
93white.onclick = function (event) {
94 if (getPresentationName()) {
95 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'white'}));
96 }
97}
98
99current.onblur = function (event) {
100 if (getPresentationName()) {
101 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'goto', value: current.value}));
102 }
103}
104
105startBtn.onclick = function (event) {
106 if (getPresentationName()) {
107 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'start'}));
108 }
109}
110
111stopBtn.onclick = function (event) {
112 if (getPresentationName()) {
113 websocket.send(JSON.stringify({presentation: getPresentationName(), action: 'stop'}));
114 }
115}
116
117current.addEventListener('keyup',function(e){
118 if (e.which == 13) this.blur();
119});
120
121
122presentation.addEventListener('change',function(event){
123 refreshInterface();
124});
125
126current_img.onclick = function (event) {
127 next.click()
128}
129
130next_img.onclick = function (event) {
131 next.click()
132}
133
134window.addEventListener('resize', function(event) {set_control_width()}, true);
135
136
137function sync_current() {
138 if (show_current.checked) {
139 current_div.style.display = "block";
140 slide_label.style.display = "none";
141 next_div.style.width = "25%";
142 } else {
143 current_div.style.display = "none";
144 slide_label.style.display = "inline";
145 next_div.style.width = "calc(100% - 20px)";
146 }
147 set_control_width();
148 saveSettings();
149}
150show_current.onclick = sync_current;
151
152function sync_next() {
153 if (show_next.checked) {
154 next_div.style.display = "block";
155 current_div.style.width = "70%";
156 } else {
157 next_div.style.display = "none";
158 current_div.style.width = "calc(100% - 20px)";
159 }
160 set_control_width();
161 saveSettings();
162}
163show_next.onclick = sync_next;
164
165function sync_shortcuts() {
166 saveSettings();
167}
168shortcuts.onclick = sync_shortcuts;
169
170function set_control_width() {
171 var width = window.innerWidth
172 || document.documentElement.clientWidth
173 || document.body.clientWidth;
174 if (show_current.checked && show_next.checked && width > 800) {
175 controls_container_inner.style.width = "70%"
176 } else {
177 controls_container_inner.style.width = "100%"
178 }
179}
180
181
182document.addEventListener('keydown', function (e) {
183 if (shortcuts.checked) {
184 switch (e.key) {
185 case "Left":
186 case "ArrowLeft":
187 case "Up":
188 case "ArrowUp":
189 case "k":
190 case "K":
191 prev.click();
192 break;
193 case " ":
194 case "Spacebar":
195 case "Enter":
196 case "Right":
197 case "ArrowRight":
198 case "Down":
199 case "ArrowDown":
200 case "j":
201 case "J":
202 next.click();
203 break;
204 case "b":
205 case "B":
206 black.click();
207 break;
208 case "w":
209 case "W":
210 white.click();
211 default:
212 return
213 }
214 }
215});
216
217function refreshInterface() {
218 var d = new Date;
219 if (Object.keys(presentationData).length > 0) {
220 currentPresentationData = presentationData[getPresentationName()];
221 presentation_text.style.display = "block";
222 status_text.innerHTML = LABEL_RUNNING;
223 startBtn.style.display = "none";
224 stopBtn.style.display = "block";
225 if (show_current.checked) {
226 switch (currentPresentationData.visible) {
227 case 3:
228 current_img.src = "/black.jpg";
229 break;
230 case 4:
231 current_img.src = "/white.jpg";
232 break;
233 default:
234 current_img.src = "/cache/" + currentPresentationData.name + "/" + currentPresentationData.slide_current + ".jpg?t=" + d.getTime();
235 break;
236 }
237 }
238 if (currentPresentationData.slide_current == currentPresentationData.slide_total) {
239 status_text.innerHTML = LABEL_FINAL_PREFIX + LABEL_RUNNING;
240 }
241 if (currentPresentationData.slide_current == currentPresentationData.slide_total + 1) {
242 status_text.innerHTML = LABEL_END_PREFIX + LABEL_RUNNING;
243 next_img.src = "/black.jpg";
244 } else {
245 next_img.src = "/cache/" + currentPresentationData.name + "/" + (currentPresentationData.slide_current + 1) + ".jpg?t=" + d.getTime();
246 }
247 if (currentPresentationData.slide_current == 0) {
248 current_img.src = "/black.jpg";
249 next_img.src = "/black.jpg";
250 status_text.innerHTML = LABEL_STOPPED;
251 startBtn.style.display = "block";
252 stopBtn.style.display = "none";
253 }
254
255 if (document.activeElement != current) {
256 current.value = currentPresentationData.slide_current;
257 }
258 total.textContent = currentPresentationData.slide_total;
259 document.title = currentPresentationData.name;
260 } else {
261 disconnect()
262 }
263}
264
265function disconnect() {
266 console.log("Disconnecting")
267 document.title = DEFAULT_TITLE;
268 current_img.src = "/black.jpg";
269 next_img.src = "/black.jpg";
270 status_text.innerHTML = LABEL_DISCONNECTED;
271 total.textContent = "?";
272 current.value = "";
273 presentation_text.style.display = "none";
274 startBtn.style.display = "none";
275 stopBtn.style.display = "none";
276}
277
278function receive_message(event) {
279 data = JSON.parse(event.data);
280 if (Object.keys(presentationData).includes(data.name)) {
281 // Existing presentation
282 presentationData[data.name] = {"name": data.name, "pres_open": data.pres_open, "slideshow": data.slideshow, "visible": data.visible, "slide_current": data.slide_current, "slide_total": data.slide_total, "option": presentationData[data.name].option};
283 } else {
284 console.log("Adding new presentation " + data.name);
285 var dropdownOption = document.createElement("option");
286 dropdownOption.textContent = data.name;
287 dropdownOption.value = data.name;
288 presentationData[data.name] = {"name": data.name, "pres_open": data.pres_open, "slideshow": data.slideshow, "visible": data.visible, "slide_current": data.slide_current, "slide_total": data.slide_total, "option": dropdownOption};
289 presentation.appendChild(dropdownOption);
290 }
291 if (! presentationData[data.name].pres_open) {
292 presentation.removeChild(presentationData[data.name].option);
293 delete presentationData[data.name]
294 disconnect()
295
296 //console.log("Deleting presentation data from list");
297 //delete presentationData[data.name];
298 //presentationOptions[data.name].remove()
299 }
300 refreshInterface()
301
302 if (preloaded == false && ! isNaN(total.textContent)) {
303 image = document.getElementById("preload_img");
304 for (let i=1; i<=Number(total.textContent); i++) {
305 image.src = "/cache/" + getPresentationName() + "/" + i + ".jpg";
306 preload.push(image);
307 }
308 preloaded = true;
309 }
310
311};