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