aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/slide-controller.js187
-rw-r--r--js/slide-deck.js32
-rw-r--r--js/slides.js5
3 files changed, 154 insertions, 70 deletions
diff --git a/js/slide-controller.js b/js/slide-controller.js
index 9dcb4df..a247b91 100644
--- a/js/slide-controller.js
+++ b/js/slide-controller.js
@@ -1,82 +1,140 @@
1/**
2 * Remote control by:
3 *
4 * @authors Pacien TRAN-GIRARD
5 */
1(function(window) { 6(function(window) {
2 7
3 var ORIGIN_ = location.protocol + '//' + location.host; 8 var ORIGIN_ = location.protocol + '//' + location.host;
4 9
5 function SlideController() { 10 function SlideController(deck) {
6 this.popup = null; 11 this.deck = deck;
7 this.isPopup = window.opener;
8 12
9 if (this.setupDone()) { 13 this.mode = null;
10 window.addEventListener('message', this.onMessage_.bind(this), 14 this.remoteSocket = null;
11 false); 15 this.isPresenter = window.opener;
12 16
13 // Close popups if we reload the main window. 17 this.keyLock = null;
14 window.addEventListener('beforeunload', function(e) { 18
15 if (this.popup) { 19 this.setup();
16 this.popup.close();
17 }
18 }.bind(this), false);
19 }
20 } 20 }
21 21
22 SlideController.PRESENTER_MODE_PARAM = 'presentme'; 22 SlideController.MODES = [ 'local', 'remote', 'controller' ];
23
24 SlideController.prototype.setup = function() {
23 25
24 SlideController.prototype.setupDone = function() { 26 var self = this;
27
28 // find the current mode
25 var params = location.search.substring(1).split('&').map(function(el) { 29 var params = location.search.substring(1).split('&').map(function(el) {
26 return el.split('='); 30 return el.split('=');
27 }); 31 });
28 32
29 var presentMe = null; 33 var paramKeys = params[0];
30 for (var i = 0, param; param = params[i]; ++i) {
31 if (param[0].toLowerCase() == SlideController.PRESENTER_MODE_PARAM) {
32 presentMe = param[1] == 'true';
33 break;
34 }
35 }
36 34
37 if (presentMe !== null) { 35 SlideController.MODES.forEach(function(element, index, array) {
38 localStorage.ENABLE_PRESENTOR_MODE = presentMe; 36 if (paramKeys.indexOf(element) > -1) {
39 // TODO: use window.history.pushState to update URL instead of the 37 self.mode = element;
40 // redirect. 38 return;
41 if (window.history.replaceState) {
42 window.history.replaceState({}, '', location.pathname);
43 } else {
44 location.replace(location.pathname);
45 return false;
46 } 39 }
47 } 40 });
41
42 console.log("Control mode: " + this.mode);
43
44 // clean the location bar
45 // if (this.mode !== null) {
46 // // localStorage.ENABLE_PRESENTOR_MODE = presentMe;
47 // if (window.history.pushState) {
48 // window.history.pushState({}, '', location.pathname);
49 // } else if (window.history.replaceState) {
50 // window.history.replaceState({}, '', location.pathname);
51 // }
52 // // else {
53 // // location.replace(location.pathname);
54 // // return false;
55 // // }
56 // }
57
58 // activate the mode specific behaviour
59 switch (this.mode) {
60
61 case 'local':
62 // Only open popup from main deck. Avoid recursive popupception.
63 if (!this.isPresenter) {
64 var opts = 'menubar=no,location=yes,resizable=yes,scrollbars=no,status=no';
65 var localPresenter = window.open(location.href, 'mywindow',
66 opts);
67
68 // Loading in the popup? Turn the presenter mode on.
69 localPresenter.addEventListener('load', function(e) {
70 localPresenter.document.body.classList
71 .add('with-notes');
72 }.bind(this), false);
73
74 window.addEventListener('message', this.onMessage_
75 .bind(this), false);
76
77 // Close popups if we reload the main window.
78 window.addEventListener('beforeunload', function(e) {
79 localPresenter.close();
80 }.bind(this), false);
81 }
82
83 break;
84
85 case 'controller':
86 this.isPresenter = true;
87 document.body.classList.add('popup');
88 document.body.classList.add('with-notes');
89 var password = prompt("Broadcaster password");
90
91 case 'remote':
92 var addr = this.deck.config_.settings.remoteSocket;
93 var channel = this.deck.config_.settings.remoteChannel;
94 var password = (password != null) ? password : '';
95 this.remoteSocket = io.connect(addr, {
96 'query' : 'channel=' + channel + '&password=' + password,
97 'force new connection' : true,
98 });
99
100 this.remoteSocket.on('connect', function() {
101 var message = 'Connected to ' + channel + '@' + addr;
102 console.log(message);
103 alert(message);
104 });
105
106 this.remoteSocket.on('disconnect', function() {
107 var message = 'Diconnected from' + channel + '@' + addr;
108 console.log(message);
109 alert(message);
110 });
111
112 this.remoteSocket.on('message', function(message) {
113 console.log('Received from remote: ' + message);
114 self.onMessage_({
115 data : {
116 keyCode : parseInt(message[0])
117 }
118 });
119 });
120
121 break;
48 122
49 var enablePresenterMode = localStorage.getItem('ENABLE_PRESENTOR_MODE');
50 if (enablePresenterMode && JSON.parse(enablePresenterMode)) {
51 // Only open popup from main deck. Don't want recursive popup
52 // opening!
53 if (!this.isPopup) {
54 var opts = 'menubar=no,location=yes,resizable=yes,scrollbars=no,status=no';
55 this.popup = window.open(location.href, 'mywindow', opts);
56
57 // Loading in the popup? Trigger the hotkey for turning
58 // presenter mode on.
59 this.popup.addEventListener('load', function(e) {
60 var evt = this.popup.document.createEvent('Event');
61 evt.initEvent('keydown', true, true);
62 evt.keyCode = 'P'.charCodeAt(0);
63 this.popup.document.dispatchEvent(evt);
64 // this.popup.document.body.classList.add('with-notes');
65 // document.body.classList.add('popup');
66 }.bind(this), false);
67 }
68 } 123 }
69 124
70 return true; 125 return true;
71 } 126 }
72 127
73 SlideController.prototype.onMessage_ = function(e) { 128 SlideController.prototype.onMessage_ = function(e) {
129 console.log("Received event: " + JSON.stringify(e));
130
74 var data = e.data; 131 var data = e.data;
75 132
76 // Restrict messages to being from this origin. Allow local developmet 133 // Restrict messages to being from this origin. Allow local developmet
77 // from file:// though. 134 // from file:// though.
78 // TODO: It would be dope if FF implemented location.origin! 135 // TODO: It would be dope if FF implemented location.origin!
79 if (e.origin != ORIGIN_ && ORIGIN_.indexOf('file://') != 0) { 136 if (this.mode === 'local' && e.origin != ORIGIN_
137 && ORIGIN_.indexOf('file://') != 0) {
80 alert('Someone tried to postMessage from an unknown origin'); 138 alert('Someone tried to postMessage from an unknown origin');
81 return; 139 return;
82 } 140 }
@@ -87,6 +145,8 @@
87 // } 145 // }
88 146
89 if ('keyCode' in data) { 147 if ('keyCode' in data) {
148 this.keyLock = data.keyCode;
149
90 var evt = document.createEvent('Event'); 150 var evt = document.createEvent('Event');
91 evt.initEvent('keydown', true, true); 151 evt.initEvent('keydown', true, true);
92 evt.keyCode = data.keyCode; 152 evt.keyCode = data.keyCode;
@@ -95,15 +155,28 @@
95 }; 155 };
96 156
97 SlideController.prototype.sendMsg = function(msg) { 157 SlideController.prototype.sendMsg = function(msg) {
158
159 if (msg.keyCode === this.keyLock) {
160 this.keyLock = null;
161 return;