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