From 4ac79e422129e654e48909017a50b066b2f587d1 Mon Sep 17 00:00:00 2001 From: pacien Date: Fri, 24 Aug 2018 01:39:40 +0200 Subject: Handle click and touch events --- pointless/viewer/stage/actions.js | 121 ++++++++++++++++++++++++++++++++++++++ pointless/viewer/stage/stage.js | 76 ++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 pointless/viewer/stage/actions.js create mode 100644 pointless/viewer/stage/stage.js (limited to 'pointless/viewer/stage') diff --git a/pointless/viewer/stage/actions.js b/pointless/viewer/stage/actions.js new file mode 100644 index 0000000..271d7b7 --- /dev/null +++ b/pointless/viewer/stage/actions.js @@ -0,0 +1,121 @@ +/* + * Pointless Viewer, a web-based Beamer presentation viewer + * Copyright (C) 2018 Pacien TRAN-GIRARD + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +"use strict"; + +class ActionEventHandler { + constructor(onNext, onPrevious) { + this.onNext = onNext; + this.onPrevious = onPrevious; + } +} + +class KeyboardEventHandler extends ActionEventHandler { + register(window) { + const self = this; + window.addEventListener("keydown", function(event) { + self._onCommand(event); + }) + } + + _onCommand(keyboardEvent) { + switch (keyboardEvent.key) { + case "Enter": + case " ": + case "ArrowRight": + case "n": + return this.onNext(); + + case "ArrowLeft": + case "p": + return this.onPrevious(); + } + } +} + +class MouseClickEventHandler extends ActionEventHandler { + register(window) { + const self = this; + window.addEventListener("click", function(event) { + self._onCommand(event); + }) + } + + _onCommand(mouseEvent) { + this.onNext(); + } +} + +class TouchSwipeEventHandler extends ActionEventHandler { + constructor(onNext, onPrevious) { + super(onNext, onPrevious); + this.touchStartEvent = null; + this.touchMoveEvent = null; + } + + register(window) { + const self = this; + + window.addEventListener("touchstart", function(event) { + event.preventDefault(); + self._onTouchStart(event); + }); + + window.addEventListener("touchmove", function(event) { + event.preventDefault(); + self._onTouchMove(event); + }); + + window.addEventListener("touchend", function(event) { + event.preventDefault(); + self._onTouchEnd(); + }); + + window.addEventListener("touchcancel", function(event) { + event.preventDefault(); + }); + } + + _onTouchStart(touchEvent) { + this.touchStartEvent = touchEvent; + } + + _onTouchMove(touchEvent) { + this.touchMoveEvent = touchEvent; + } + + _onTouchEnd() { + if (this.touchStartEvent == null || this.touchMoveEvent == null) return; + + const touchDown = this._xCoordinate(this.touchStartEvent); + const touchUp = this._xCoordinate(this.touchMoveEvent); + const xDelta = touchDown - touchUp; + + if (xDelta > 0) + this.onNext(); + else if (xDelta < 0) + this.onPrevious(); + + this.touchStartEvent = null; + this.touchMoveEvent = null; + } + + _xCoordinate(touchEvent) { + return touchEvent.touches[0].clientX; // first finger + } +} diff --git a/pointless/viewer/stage/stage.js b/pointless/viewer/stage/stage.js new file mode 100644 index 0000000..e9a2d38 --- /dev/null +++ b/pointless/viewer/stage/stage.js @@ -0,0 +1,76 @@ +/* + * Pointless Viewer, a web-based Beamer presentation viewer + * Copyright (C) 2018 Pacien TRAN-GIRARD + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +"use strict"; + +class Stage { + constructor(onReady, onNext, onPrevious) { + this.audienceScreen = null; + this.presenterScreen = null; + + this.projector = window.open(window.location.href, "_blank", "toolbar=0,location=0,menubar=0"); + if (this.projector == null) + alert("Please allow pop-ups, then refresh this page."); + + const self = this; + this.projector.addEventListener("load", function() { + self.audienceScreen = new Screen(self.projector, false, false); + self.presenterScreen = new Screen(window, true, true); + self._watchDetach(); + onReady(); + }); + + this.eventHandlers = [ + new KeyboardEventHandler(onNext, onPrevious), + new MouseClickEventHandler(onNext, onPrevious), + new TouchSwipeEventHandler(onNext, onPrevious) + ]; + + this._registerEventHandler(window); + this._registerEventHandler(this.projector); + } + + setPage(page) { + this.audienceScreen.setPage(page); + this.presenterScreen.setPage(page); + } + + _registerEventHandler(window) { + if (window == null) return; + + this.eventHandlers.forEach(function(eventHandler) { + eventHandler.register(window); + }); + } + + _watchDetach() { + const self = this; + window.addEventListener("beforeunload", function() { + self._setMessage(self.projector, "Controller detached"); + }); + + this.projector.addEventListener("beforeunload", function() { + self._setMessage(window, "Viewer detached"); + }); + } + + _setMessage(window, message) { + const messageBar = window.document.getElementById("message"); + messageBar.textContent = message; + } +} -- cgit v1.2.3