From add331408b0f207b82f3ec1b76251c700197e807 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Mon, 16 Jun 2014 19:30:53 +0200 Subject: Import slides --- slides/final/js/slide-controller.js | 227 ++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 slides/final/js/slide-controller.js (limited to 'slides/final/js/slide-controller.js') diff --git a/slides/final/js/slide-controller.js b/slides/final/js/slide-controller.js new file mode 100644 index 0000000..2fb2560 --- /dev/null +++ b/slides/final/js/slide-controller.js @@ -0,0 +1,227 @@ +/** + * Remote control by: + * + * @authors Pacien TRAN-GIRARD + */ +(function(window) { + + var ORIGIN_ = location.protocol + '//' + location.host; + + function SlideController(deck) { + this.deck = deck; + + this.mode = null; + this.remoteSocket = null; + this.isPresenter = false; + this.isController = false; + + this.keyLock = null; + + this.setup(); + }; + + SlideController.MODES = ['local', 'remote', 'controller', 'presenter']; + + SlideController.prototype.setup = function() { + + var self = this; + + // find the current mode + var params = location.search.substring(1).split('&').map(function(el) { + return el.split('='); + }); + + var paramKeys = params[0]; + + SlideController.MODES.forEach(function(element, index, array) { + if (paramKeys.indexOf(element) > -1) { + self.mode = element; + return; + } + }); + + console.log("Control mode: " + this.mode); + + // clean the location bar + // if (this.mode !== null) { + // // localStorage.ENABLE_PRESENTOR_MODE = presentMe; + // if (window.history.pushState) { + // window.history.pushState({}, '', location.pathname); + // } else if (window.history.replaceState) { + // window.history.replaceState({}, '', location.pathname); + // } + // // else { + // // location.replace(location.pathname); + // // return false; + // // } + // } + + // activate the mode specific behaviour + switch (this.mode) { + + case 'local': + // Only open popup from main deck. Avoid recursive popupception. + if (!this.isPresenter) { + var opts = 'menubar=no,location=yes,resizable=yes,scrollbars=no,status=no'; + var localPresenter = window.open(location.href, 'mywindow', opts); + + // Loading in the popup? Turn the presenter mode on. + localPresenter.addEventListener('load', function(e) { + localPresenter.document.body.classList.add('popup'); + localPresenter.document.body.classList.add('with-notes'); + }.bind(this), false); + + window.addEventListener('message', this.onMessage_.bind(this), false); + + // Close popups if we reload the main window. + window.addEventListener('beforeunload', function(e) { + localPresenter.close(); + }.bind(this), false); + } + + break; + + case 'presenter': + this.isPresenter = true; + document.body.classList.add('popup'); + + case 'controller': + this.isController = true; + document.body.classList.add('with-notes'); + var password = prompt("Broadcaster password"); + + case 'remote': + + var addr = this.deck.config_.settings.remoteSocket; + var channel = this.deck.config_.settings.remoteChannel; + var password = (password != null) ? password : ''; + + require(['humane-themed', addr + 'socket.io/socket.io.js'], function(humane, io) { + + self.remoteSocket = io.connect(addr, { + 'query' : 'channel=' + channel + '&password=' + password, + 'force new connection' : true, + }); + + self.remoteSocket.on('connecting', function() { + console.log('Connecting to ' + channel + '@' + addr); + humane.remove(); + humane.log('Connecting...', { + timeout : 0 + }); + }); + + self.remoteSocket.on('connect', function() { + console.log('Connected to ' + channel + '@' + addr); + humane.remove(); + humane.log('Connected'); + }); + + self.remoteSocket.on('connect_failed', function() { + console.log('Error connecting to ' + channel + '@' + addr); + humane.remove(); + humane.log('Connection failed', { + timeout : 0 + }); + }); + + self.remoteSocket.on('error', function() { + console.log('Error on ' + channel + '@' + addr); + humane.remove(); + humane.log('Error', { + timeout : 0 + }); + }); + + self.remoteSocket.on('disconnect', function() { + console.log('Diconnected from' + channel + '@' + addr); + humane.remove(); + humane.log('Disconnected'); + }); + + self.remoteSocket.on('message', function(message) { + console.log('Received from remote: ' + message); + self.onMessage_({ + data : { + keyCode : parseInt(message[0]) + } + }); + }); + }); + + break; + + } + + return true; + }; + + SlideController.prototype.onMessage_ = function(e) { + + var data = e.data; + + console.log("Received event: " + JSON.stringify(data)); + + // Restrict messages to being from this origin. Allow local developmet + // from file:// though. + // TODO: It would be dope if FF implemented location.origin! + if (this.mode === 'local' && e.origin != ORIGIN_ && ORIGIN_.indexOf('file://') != 0) { + alert('Someone tried to postMessage from an unknown origin'); + return; + } + + // if (e.source.location.hostname != 'localhost') { + // alert('Someone tried to postMessage from an unknown origin'); + // return; + // } + + if ('keyCode' in data) { + if (isNaN(data.keyCode)) { + return; + } + + this.keyLock = data.keyCode; + + var evt = document.createEvent('Event'); + evt.initEvent('keydown', true, true); + evt.keyCode = data.keyCode; + document.dispatchEvent(evt); + } + }; + + SlideController.prototype.sendMsg = function(msg) { + + if (msg.keyCode === this.keyLock) { + this.keyLock = null; + return; + } + + // don't toggle speaker's notes for viewers + if (msg.keyCode === 80) { + return; + } + + console.log("Sending: " + JSON.stringify(msg)); + + // // Send message to popup window. + // if (this.localPresenter) { + // this.localPresenter.postMessage(msg, ORIGIN_); + // } + + // Send message to main window. + if (this.isController) { + switch (this.mode) { + case 'local': + // TODO: It would be dope if FF implemented location.origin. + window.opener.postMessage(msg, '*'); + break; + case 'controller': + case 'presenter': + this.remoteSocket.emit('message', msg.keyCode); + } + } + }; + + window.SlideController = SlideController; + +})(window); -- cgit v1.2.3