]>
Commit | Line | Data |
---|---|---|
15046f00 JM |
1 | /* |
2 | * noVNC: HTML5 VNC client | |
3 | * Copyright (C) 2010 Joel Martin | |
5f409eee | 4 | * Licensed under LGPL-3 (see LICENSE.txt) |
15046f00 JM |
5 | * |
6 | * See README.md for usage and integration instructions. | |
7 | */ | |
8 | "use strict"; | |
8db09746 | 9 | /*jslint white: false */ |
a7a89626 | 10 | /*global $, Util, RFB, Canvas, VNC_uri_prefix, Element, Fx */ |
15046f00 | 11 | |
63708ff5 | 12 | var DefaultControls = { |
91308399 | 13 | |
da6dd893 JM |
14 | settingsOpen : false, |
15 | ||
16 | // Render default controls and initialize settings menu | |
91308399 | 17 | load: function(target) { |
a7a89626 | 18 | var html, i, DC = DefaultControls, sheet, sheets, llevels; |
91308399 | 19 | |
91308399 JM |
20 | /* Populate the 'target' DOM element with default controls */ |
21 | if (!target) { target = 'vnc'; } | |
22 | ||
23 | html = ""; | |
24 | html += '<div id="VNC_controls">'; | |
25 | html += ' <ul>'; | |
26 | html += ' <li>Host: <input id="VNC_host"></li>'; | |
27 | html += ' <li>Port: <input id="VNC_port"></li>'; | |
28 | html += ' <li>Password: <input id="VNC_password"'; | |
29 | html += ' type="password"></li>'; | |
91308399 JM |
30 | html += ' <li><input id="VNC_connect_button" type="button"'; |
31 | html += ' value="Loading" disabled></li>'; | |
32 | html += ' </ul>'; | |
33 | html += '</div>'; | |
34 | html += '<div id="VNC_screen">'; | |
63708ff5 JM |
35 | html += ' <div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">'; |
36 | html += ' <table border=0 width=100%><tr>'; | |
37 | html += ' <td><div id="VNC_status">Loading</div></td>'; | |
da6dd893 JM |
38 | html += ' <td width=1%><div class="VNC_buttons_right">'; |
39 | html += ' <input type=button class="VNC_status_button" value="Settings"'; | |
40 | html += ' id="menuButton"'; | |
41 | html += ' onclick="DefaultControls.clickSettingsMenu();">'; | |
42 | html += ' <span id="VNC_settings_menu"'; | |
43 | html += ' onmouseover="DefaultControls.canvasBlur();"'; | |
44 | html += ' onmouseout="DefaultControls.canvasFocus();">'; | |
45 | html += ' <ul>'; | |
46 | html += ' <li><input id="VNC_encrypt"'; | |
208c832b | 47 | html += ' type="checkbox"> Encrypt</li>'; |
da6dd893 JM |
48 | html += ' <li><input id="VNC_true_color"'; |
49 | html += ' type="checkbox" checked> True Color</li>'; | |
50 | html += ' <li><input id="VNC_cursor"'; | |
31a837d5 | 51 | html += ' type="checkbox"> Local Cursor</li>'; |
ff36b127 JM |
52 | html += ' <li><input id="VNC_connectTimeout"'; |
53 | html += ' type="input"> Connect Timeout (s)</li>'; | |
da6dd893 JM |
54 | html += ' <hr>'; |
55 | ||
56 | // Stylesheet selection dropdown | |
57 | html += ' <li><select id="VNC_stylesheet" name="vncStyle">'; | |
58 | html += ' <option value="default">default</option>'; | |
8d5d2c82 AM |
59 | sheet = WebUtil.selectStylesheet(); |
60 | sheets = WebUtil.getStylesheets(); | |
8db09746 | 61 | for (i = 0; i < sheets.length; i += 1) { |
da6dd893 JM |
62 | html += '<option value="' + sheets[i].title + '">' + sheets[i].title + '</option>'; |
63 | } | |
64 | html += ' </select> Style</li>'; | |
65 | ||
66 | // Logging selection dropdown | |
67 | html += ' <li><select id="VNC_logging" name="vncLogging">'; | |
68 | llevels = ['error', 'warn', 'info', 'debug']; | |
8db09746 | 69 | for (i = 0; i < llevels.length; i += 1) { |
da6dd893 JM |
70 | html += '<option value="' + llevels[i] + '">' + llevels[i] + '</option>'; |
71 | } | |
72 | html += ' </select> Logging</li>'; | |
73 | ||
74 | html += ' <hr>'; | |
75 | html += ' <li><input type="button" id="VNC_apply" value="Apply"'; | |
76 | html += ' onclick="DefaultControls.settingsApply()"></li>'; | |
77 | html += ' </ul>'; | |
78 | html += ' </span></div></td>'; | |
79 | html += ' <td width=1%><div class="VNC_buttons_right">'; | |
80 | html += ' <input type=button class="VNC_status_button" value="Send CtrlAltDel"'; | |
160fabf6 | 81 | html += ' id="sendCtrlAltDelButton"'; |
63708ff5 JM |
82 | html += ' onclick="DefaultControls.sendCtrlAltDel();"></div></td>'; |
83 | html += ' </tr></table>'; | |
84 | html += ' </div>'; | |
91308399 JM |
85 | html += ' <canvas id="VNC_canvas" width="640px" height="20px">'; |
86 | html += ' Canvas not supported.'; | |
87 | html += ' </canvas>'; | |
88 | html += '</div>'; | |
89 | html += '<br><br>'; | |
90 | html += '<div id="VNC_clipboard">'; | |
91 | html += ' VNC Clipboard:'; | |
92 | html += ' <input id="VNC_clipboard_clear_button"'; | |
93 | html += ' type="button" value="Clear"'; | |
94 | html += ' onclick="DefaultControls.clipClear();">'; | |
95 | html += ' <br>'; | |
96 | html += ' <textarea id="VNC_clipboard_text" cols=80 rows=5'; | |
da6dd893 JM |
97 | html += ' onfocus="DefaultControls.canvasBlur();"'; |
98 | html += ' onblur="DefaultControls.canvasFocus();"'; | |
91308399 JM |
99 | html += ' onchange="DefaultControls.clipSend();"></textarea>'; |
100 | html += '</div>'; | |
101 | $(target).innerHTML = html; | |
102 | ||
da6dd893 | 103 | // Settings with immediate effects |
19463eac | 104 | DC.initSetting('logging', 'warn'); |
8d5d2c82 | 105 | WebUtil.init_logging(DC.getSetting('logging')); |
da6dd893 | 106 | DC.initSetting('stylesheet', 'default'); |
8db09746 | 107 | |
8d5d2c82 AM |
108 | WebUtil.selectStylesheet(null); // call twice to get around webkit bug |
109 | WebUtil.selectStylesheet(DC.getSetting('stylesheet')); | |
da6dd893 | 110 | |
91308399 | 111 | /* Populate the controls if defaults are provided in the URL */ |
da6dd893 JM |
112 | DC.initSetting('host', ''); |
113 | DC.initSetting('port', ''); | |
114 | DC.initSetting('password', ''); | |
208c832b | 115 | DC.initSetting('encrypt', false); |
da6dd893 | 116 | DC.initSetting('true_color', true); |
31a837d5 | 117 | DC.initSetting('cursor', false); |
ff36b127 | 118 | DC.initSetting('connectTimeout', 2); |
3954ae14 | 119 | |
8db09746 JM |
120 | DC.rfb = RFB({'target': 'VNC_canvas', |
121 | 'updateState': DC.updateState, | |
122 | 'clipboardReceive': DC.clipReceive}); | |
8db09746 JM |
123 | |
124 | // Unfocus clipboard when over the VNC area | |
3954ae14 | 125 | $('VNC_screen').onmousemove = function () { |
8db09746 JM |
126 | var canvas = DC.rfb.get_canvas(); |
127 | if ((! canvas) || (! canvas.get_focused())) { | |
3954ae14 JM |
128 | $('VNC_clipboard_text').blur(); |
129 | } | |
130 | }; | |
8db09746 | 131 | |
91308399 JM |
132 | }, |
133 | ||
da6dd893 JM |
134 | // Read form control compatible setting from cookie |
135 | getSetting: function(name) { | |
136 | var val, ctrl = $('VNC_' + name); | |
8d5d2c82 | 137 | val = WebUtil.readCookie(name); |
da6dd893 JM |
138 | if (ctrl.type === 'checkbox') { |
139 | if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) { | |
140 | val = false; | |
141 | } else { | |
142 | val = true; | |
143 | } | |
144 | } | |
145 | return val; | |
146 | }, | |
147 | ||
148 | // Update cookie and form control setting. If value is not set, then | |
149 | // updates from control to current cookie setting. | |
150 | updateSetting: function(name, value) { | |
151 | var i, ctrl = $('VNC_' + name); | |
152 | // Save the cookie for this session | |
153 | if (typeof value !== 'undefined') { | |
8d5d2c82 | 154 | WebUtil.createCookie(name, value); |
da6dd893 JM |
155 | } |
156 | ||
157 | // Update the settings control | |
158 | value = DefaultControls.getSetting(name); | |
159 | if (ctrl.type === 'checkbox') { | |
160 | ctrl.checked = value; | |
161 | } else if (typeof ctrl.options !== 'undefined') { | |
8db09746 | 162 | for (i = 0; i < ctrl.options.length; i += 1) { |
da6dd893 JM |
163 | if (ctrl.options[i].value === value) { |
164 | ctrl.selectedIndex = i; | |
165 | break; | |
166 | } | |
167 | } | |
168 | } else { | |
169 | ctrl.value = value; | |
170 | } | |
171 | }, | |
172 | ||
173 | // Save control setting to cookie | |
174 | saveSetting: function(name) { | |
175 | var val, ctrl = $('VNC_' + name); | |
176 | if (ctrl.type === 'checkbox') { | |
177 | val = ctrl.checked; | |
178 | } else if (typeof ctrl.options !== 'undefined') { | |
179 | val = ctrl.options[ctrl.selectedIndex].value; | |
180 | } else { | |
181 | val = ctrl.value; | |
182 | } | |
8d5d2c82 | 183 | WebUtil.createCookie(name, val); |
8db09746 | 184 | //Util.Debug("Setting saved '" + name + "=" + val + "'"); |
da6dd893 JM |
185 | return val; |
186 | }, | |
187 | ||
188 | // Initial page load read/initialization of settings | |
189 | initSetting: function(name, defVal) { | |
a8edf9d8 | 190 | var val; |
da6dd893 JM |
191 | |
192 | // Check Query string followed by cookie | |
8d5d2c82 | 193 | val = WebUtil.getQueryVar(name); |
da6dd893 | 194 | if (val === null) { |
8d5d2c82 | 195 | val = WebUtil.readCookie(name, defVal); |
da6dd893 | 196 | } |
a8edf9d8 | 197 | DefaultControls.updateSetting(name, val); |
8db09746 | 198 | //Util.Debug("Setting '" + name + "' initialized to '" + val + "'"); |
da6dd893 JM |
199 | return val; |
200 | }, | |
201 | ||
202 | ||
203 | // Toggle the settings menu: | |
204 | // On open, settings are refreshed from saved cookies. | |
205 | // On close, settings are applied | |
206 | clickSettingsMenu: function() { | |
207 | var DC = DefaultControls; | |
a8edf9d8 | 208 | if (DC.settingsOpen) { |
da6dd893 JM |
209 | DC.settingsApply(); |
210 | ||
211 | DC.closeSettingsMenu(); | |
212 | } else { | |
213 | DC.updateSetting('encrypt'); | |
da6dd893 | 214 | DC.updateSetting('true_color'); |
8db09746 | 215 | if (DC.rfb.get_canvas().get_cursor_uri()) { |
da6dd893 JM |
216 | DC.updateSetting('cursor'); |
217 | } else { | |
f7f69d8e | 218 | DC.updateSetting('cursor', false); |
da6dd893 JM |
219 | $('VNC_cursor').disabled = true; |
220 | } | |
ff36b127 | 221 | DC.updateSetting('connectTimeout'); |
da6dd893 JM |
222 | DC.updateSetting('stylesheet'); |
223 | DC.updateSetting('logging'); | |
224 | ||
225 | DC.openSettingsMenu(); | |
226 | } | |
227 | }, | |
228 | ||
229 | // Open menu | |
230 | openSettingsMenu: function() { | |
231 | $('VNC_settings_menu').style.display = "block"; | |
232 | DefaultControls.settingsOpen = true; | |
233 | }, | |
234 | ||
235 | // Close menu (without applying settings) | |
236 | closeSettingsMenu: function() { | |
237 | $('VNC_settings_menu').style.display = "none"; | |
238 | DefaultControls.settingsOpen = false; | |
239 | }, | |
240 | ||
241 | // Disable/enable controls depending on connection state | |
b5087acc JM |
242 | settingsDisabled: function(disabled, rfb) { |
243 | //Util.Debug(">> settingsDisabled"); | |
da6dd893 | 244 | $('VNC_encrypt').disabled = disabled; |
da6dd893 | 245 | $('VNC_true_color').disabled = disabled; |
b5087acc | 246 | if (rfb && rfb.get_canvas().get_cursor_uri()) { |
da6dd893 JM |
247 | $('VNC_cursor').disabled = disabled; |
248 | } else { | |
f7f69d8e | 249 | DefaultControls.updateSetting('cursor', false); |
da6dd893 JM |
250 | $('VNC_cursor').disabled = true; |
251 | } | |
ff36b127 | 252 | $('VNC_connectTimeout').disabled = disabled; |
b5087acc | 253 | //Util.Debug("<< settingsDisabled"); |
da6dd893 JM |
254 | }, |
255 | ||
256 | // Save/apply settings when 'Apply' button is pressed | |
257 | settingsApply: function() { | |
8db09746 | 258 | //Util.Debug(">> settingsApply"); |
a7a89626 | 259 | var DC = DefaultControls; |
da6dd893 | 260 | DC.saveSetting('encrypt'); |
da6dd893 | 261 | DC.saveSetting('true_color'); |
8db09746 | 262 | if (DC.rfb.get_canvas().get_cursor_uri()) { |
da6dd893 JM |
263 | DC.saveSetting('cursor'); |
264 | } | |
ff36b127 | 265 | DC.saveSetting('connectTimeout'); |
da6dd893 JM |
266 | DC.saveSetting('stylesheet'); |
267 | DC.saveSetting('logging'); | |
268 | ||
269 | // Settings with immediate (non-connected related) effect | |
8d5d2c82 AM |
270 | WebUtil.selectStylesheet(DC.getSetting('stylesheet')); |
271 | WebUtil.init_logging(DC.getSetting('logging')); | |
da6dd893 | 272 | |
8db09746 | 273 | //Util.Debug("<< settingsApply"); |
da6dd893 JM |
274 | }, |
275 | ||
276 | ||
277 | ||
f00b1e37 | 278 | setPassword: function() { |
8db09746 | 279 | DefaultControls.rfb.sendPassword($('VNC_password').value); |
f00b1e37 JM |
280 | return false; |
281 | }, | |
282 | ||
63708ff5 | 283 | sendCtrlAltDel: function() { |
8db09746 | 284 | DefaultControls.rfb.sendCtrlAltDel(); |
63708ff5 JM |
285 | }, |
286 | ||
8db09746 | 287 | updateState: function(rfb, state, oldstate, msg) { |
a7a89626 | 288 | var s, sb, c, cad, klass; |
91308399 | 289 | s = $('VNC_status'); |
63708ff5 | 290 | sb = $('VNC_status_bar'); |
91308399 | 291 | c = $('VNC_connect_button'); |
160fabf6 | 292 | cad = $('sendCtrlAltDelButton'); |
91308399 JM |
293 | switch (state) { |
294 | case 'failed': | |
f00b1e37 | 295 | case 'fatal': |
91308399 | 296 | c.disabled = true; |
160fabf6 | 297 | cad.disabled = true; |
b5087acc | 298 | DefaultControls.settingsDisabled(true, rfb); |
91308399 JM |
299 | klass = "VNC_status_error"; |
300 | break; | |
301 | case 'normal': | |
302 | c.value = "Disconnect"; | |
303 | c.onclick = DefaultControls.disconnect; | |
304 | c.disabled = false; | |
160fabf6 | 305 | cad.disabled = false; |
b5087acc | 306 | DefaultControls.settingsDisabled(true, rfb); |
91308399 JM |
307 | klass = "VNC_status_normal"; |
308 | break; | |
309 | case 'disconnected': | |
f00b1e37 | 310 | case 'loaded': |
91308399 JM |
311 | c.value = "Connect"; |
312 | c.onclick = DefaultControls.connect; | |
313 | ||
314 | c.disabled = false; | |
160fabf6 | 315 | cad.disabled = true; |
b5087acc | 316 | DefaultControls.settingsDisabled(false, rfb); |
91308399 JM |
317 | klass = "VNC_status_normal"; |
318 | break; | |
f00b1e37 JM |
319 | case 'password': |
320 | c.value = "Send Password"; | |
321 | c.onclick = DefaultControls.setPassword; | |
322 | ||
323 | c.disabled = false; | |
324 | cad.disabled = true; | |
b5087acc | 325 | DefaultControls.settingsDisabled(true, rfb); |
f00b1e37 JM |
326 | klass = "VNC_status_warn"; |
327 | break; | |
91308399 JM |
328 | default: |
329 | c.disabled = true; | |
160fabf6 | 330 | cad.disabled = true; |
b5087acc | 331 | DefaultControls.settingsDisabled(true, rfb); |
91308399 JM |
332 | klass = "VNC_status_warn"; |
333 | break; | |
334 | } | |
335 | ||
336 | if (typeof(msg) !== 'undefined') { | |
337 | s.setAttribute("class", klass); | |
63708ff5 | 338 | sb.setAttribute("class", klass); |
91308399 JM |
339 | s.innerHTML = msg; |
340 | } | |
341 | ||
342 | }, | |
343 | ||
8db09746 JM |
344 | clipReceive: function(rfb, text) { |
345 | Util.Debug(">> DefaultControls.clipReceive: " + text.substr(0,40) + "..."); | |
346 | $('VNC_clipboard_text').value = text; | |
347 | Util.Debug("<< DefaultControls.clipReceive"); | |
348 | }, | |
349 | ||
350 | ||
91308399 | 351 | connect: function() { |
da6dd893 JM |
352 | var host, port, password, DC = DefaultControls; |
353 | ||
354 | DC.closeSettingsMenu(); | |
355 | ||
91308399 JM |
356 | host = $('VNC_host').value; |
357 | port = $('VNC_port').value; | |
358 | password = $('VNC_password').value; | |
91308399 | 359 | if ((!host) || (!port)) { |
63708ff5 | 360 | throw("Must set host and port"); |
91308399 JM |
361 | } |
362 | ||
8db09746 | 363 | DC.rfb.set_encrypt(DC.getSetting('encrypt')); |
8db09746 JM |
364 | DC.rfb.set_true_color(DC.getSetting('true_color')); |
365 | DC.rfb.set_local_cursor(DC.getSetting('cursor')); | |
ff36b127 | 366 | DC.rfb.set_connectTimeout(DC.getSetting('connectTimeout')); |
da6dd893 | 367 | |
8db09746 | 368 | DC.rfb.connect(host, port, password); |
91308399 JM |
369 | }, |
370 | ||
371 | disconnect: function() { | |
da6dd893 JM |
372 | DefaultControls.closeSettingsMenu(); |
373 | ||
8db09746 | 374 | DefaultControls.rfb.disconnect(); |
91308399 JM |
375 | }, |
376 | ||
da6dd893 | 377 | canvasBlur: function() { |
8db09746 | 378 | DefaultControls.rfb.get_canvas().set_focused(false); |
91308399 JM |
379 | }, |
380 | ||
da6dd893 | 381 | canvasFocus: function() { |
8db09746 | 382 | DefaultControls.rfb.get_canvas().set_focused(true); |
91308399 JM |
383 | }, |
384 | ||
385 | clipClear: function() { | |
386 | $('VNC_clipboard_text').value = ""; | |
8db09746 | 387 | DefaultControls.rfb.clipboardPasteFrom(""); |
91308399 JM |
388 | }, |
389 | ||
390 | clipSend: function() { | |
391 | var text = $('VNC_clipboard_text').value; | |
81e5adaf | 392 | Util.Debug(">> DefaultControls.clipSend: " + text.substr(0,40) + "..."); |
8db09746 | 393 | DefaultControls.rfb.clipboardPasteFrom(text); |
81e5adaf | 394 | Util.Debug("<< DefaultControls.clipSend"); |
91308399 JM |
395 | } |
396 | ||
63708ff5 | 397 | }; |