]> git.proxmox.com Git - mirror_novnc.git/blame - include/ui.js
Fix websockify with python2.4
[mirror_novnc.git] / include / ui.js
CommitLineData
15046f00
JM
1/*
2 * noVNC: HTML5 VNC client
d0c29bb6 3 * Copyright (C) 2011 Joel Martin
5f409eee 4 * Licensed under LGPL-3 (see LICENSE.txt)
15046f00
JM
5 *
6 * See README.md for usage and integration instructions.
7 */
43cf7bd8 8
15046f00 9"use strict";
43cf7bd8 10/*jslint white: false, browser: true */
d890e864 11/*global window, $D, Util, WebUtil, RFB, Display */
15046f00 12
f7ec5b2c 13var UI = {
91308399 14
da6dd893
JM
15settingsOpen : false,
16
f7ec5b2c 17// Render default UI and initialize settings menu
91308399 18load: function(target) {
f7ec5b2c 19 var html = '', i, sheet, sheets, llevels;
91308399 20
f7ec5b2c 21 /* Populate the 'target' DOM element with default UI */
e4671910
JM
22 if (!target) {
23 target = $D('vnc');
24 } else if (typeof target === 'string') {
25 target = $D(target);
26 }
91308399 27
e66f3f89
JM
28 if ((!document.createElement('canvas').getContext) &&
29 window.ActiveXObject) {
30 // Suggest Chrome frame for Internet Explorer users
31 html += '<center><div style="text-align: left; width: 400px">';
32 html += ' You are using a version of Internet Explorer ';
33 html += ' that does not have HTML5 Canvas support. ';
34 html += ' To use noVNC you must use a browser with HTML5 ';
35 html += ' Canvas support or install ';
36 html += ' <a href="http://google.com/chromeframe" target="cframe">';
37 html += ' Google Chrome Frame.</a>';
38 html += '</div></center>';
e4671910 39 target.innerHTML = html;
e66f3f89
JM
40 return;
41 }
42
91308399
JM
43 html += '<div id="VNC_controls">';
44 html += ' <ul>';
45 html += ' <li>Host: <input id="VNC_host"></li>';
46 html += ' <li>Port: <input id="VNC_port"></li>';
47 html += ' <li>Password: <input id="VNC_password"';
48 html += ' type="password"></li>';
91308399
JM
49 html += ' <li><input id="VNC_connect_button" type="button"';
50 html += ' value="Loading" disabled></li>';
51 html += ' </ul>';
52 html += '</div>';
53 html += '<div id="VNC_screen">';
63708ff5
JM
54 html += ' <div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">';
55 html += ' <table border=0 width=100%><tr>';
56 html += ' <td><div id="VNC_status">Loading</div></td>';
ad3f7624
JM
57
58 // Mouse button selectors for touch devices
59 html += ' <td width=1%><div class="VNC_buttons_right">';
60 html += ' <nobr><span id="VNC_mouse_buttons" style="display: none;">';
61 html += ' <input type="button" class="VNC_status_button"';
62 html += ' id="VNC_mouse_button1" value="L" onclick="UI.setMouseButton(1);"';
63 html += ' ><input type="button" class="VNC_status_button"';
64 html += ' id="VNC_mouse_button2" value="M" onclick="UI.setMouseButton(2);"';
65 html += ' ><input type="button" class="VNC_status_button"';
66 html += ' id="VNC_mouse_button4" value="R" onclick="UI.setMouseButton(4);">';
67 html += ' </span></nobr></div></td>';
68
69 // Settings drop-down menu
da6dd893
JM
70 html += ' <td width=1%><div class="VNC_buttons_right">';
71 html += ' <input type=button class="VNC_status_button" value="Settings"';
72 html += ' id="menuButton"';
f7ec5b2c 73 html += ' onclick="UI.clickSettingsMenu();">';
da6dd893 74 html += ' <span id="VNC_settings_menu"';
d890e864
JM
75 html += ' onmouseover="UI.displayBlur();"';
76 html += ' onmouseout="UI.displayFocus();">';
da6dd893
JM
77 html += ' <ul>';
78 html += ' <li><input id="VNC_encrypt"';
208c832b 79 html += ' type="checkbox"> Encrypt</li>';
da6dd893
JM
80 html += ' <li><input id="VNC_true_color"';
81 html += ' type="checkbox" checked> True Color</li>';
82 html += ' <li><input id="VNC_cursor"';
31a837d5 83 html += ' type="checkbox"> Local Cursor</li>';
f1a9971c
JM
84 html += ' <li><input id="VNC_shared"';
85 html += ' type="checkbox"> Shared Mode</li>';
ff36b127
JM
86 html += ' <li><input id="VNC_connectTimeout"';
87 html += ' type="input"> Connect Timeout (s)</li>';
da6dd893
JM
88 html += ' <hr>';
89
90 // Stylesheet selection dropdown
91 html += ' <li><select id="VNC_stylesheet" name="vncStyle">';
92 html += ' <option value="default">default</option>';
8d5d2c82
AM
93 sheet = WebUtil.selectStylesheet();
94 sheets = WebUtil.getStylesheets();
8db09746 95 for (i = 0; i < sheets.length; i += 1) {
da6dd893
JM
96 html += '<option value="' + sheets[i].title + '">' + sheets[i].title + '</option>';
97 }
98 html += ' </select> Style</li>';
99
100 // Logging selection dropdown
101 html += ' <li><select id="VNC_logging" name="vncLogging">';
102 llevels = ['error', 'warn', 'info', 'debug'];
8db09746 103 for (i = 0; i < llevels.length; i += 1) {
da6dd893
JM
104 html += '<option value="' + llevels[i] + '">' + llevels[i] + '</option>';
105 }
106 html += ' </select> Logging</li>';
107
108 html += ' <hr>';
109 html += ' <li><input type="button" id="VNC_apply" value="Apply"';
f7ec5b2c 110 html += ' onclick="UI.settingsApply()"></li>';
da6dd893
JM
111 html += ' </ul>';
112 html += ' </span></div></td>';
ad3f7624
JM
113
114 // CtrlAltDel Button
da6dd893 115 html += ' <td width=1%><div class="VNC_buttons_right">';
ad3f7624 116 html += ' <input type=button class="VNC_status_button" value="CtrlAltDel"';
160fabf6 117 html += ' id="sendCtrlAltDelButton"';
f7ec5b2c 118 html += ' onclick="UI.sendCtrlAltDel();"></div></td>';
ad3f7624 119
63708ff5
JM
120 html += ' </tr></table>';
121 html += ' </div>';
91308399
JM
122 html += ' <canvas id="VNC_canvas" width="640px" height="20px">';
123 html += ' Canvas not supported.';
124 html += ' </canvas>';
125 html += '</div>';
126 html += '<br><br>';
127 html += '<div id="VNC_clipboard">';
128 html += ' VNC Clipboard:';
129 html += ' <input id="VNC_clipboard_clear_button"';
130 html += ' type="button" value="Clear"';
f7ec5b2c 131 html += ' onclick="UI.clipClear();">';
91308399
JM
132 html += ' <br>';
133 html += ' <textarea id="VNC_clipboard_text" cols=80 rows=5';
d890e864
JM
134 html += ' onfocus="UI.displayBlur();"';
135 html += ' onblur="UI.displayFocus();"';
f7ec5b2c 136 html += ' onchange="UI.clipSend();"></textarea>';
91308399 137 html += '</div>';
e4671910 138 target.innerHTML = html;
91308399 139
da6dd893 140 // Settings with immediate effects
f7ec5b2c
JM
141 UI.initSetting('logging', 'warn');
142 WebUtil.init_logging(UI.getSetting('logging'));
143 UI.initSetting('stylesheet', 'default');
8db09746 144
8d5d2c82 145 WebUtil.selectStylesheet(null); // call twice to get around webkit bug
f7ec5b2c 146 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
da6dd893 147
91308399 148 /* Populate the controls if defaults are provided in the URL */
f7ec5b2c
JM
149 UI.initSetting('host', '');
150 UI.initSetting('port', '');
151 UI.initSetting('password', '');
152 UI.initSetting('encrypt', false);
153 UI.initSetting('true_color', true);
154 UI.initSetting('cursor', false);
155 UI.initSetting('shared', true);
156 UI.initSetting('connectTimeout', 2);
157
e4671910 158 UI.rfb = RFB({'target': $D('VNC_canvas'),
d890e864
JM
159 'onUpdateState': UI.updateState,
160 'onClipboard': UI.clipReceive});
8db09746
JM
161
162 // Unfocus clipboard when over the VNC area
e4671910 163 $D('VNC_screen').onmousemove = function () {
d1bd5ec7
JM
164 var keyboard = UI.rfb.get_keyboard();
165 if ((! keyboard) || (! keyboard.get_focused())) {
e4671910 166 $D('VNC_clipboard_text').blur();
3954ae14
JM
167 }
168 };
8db09746 169
ad3f7624
JM
170 // Show mouse selector buttons on touch screen devices
171 if ('ontouchstart' in document.documentElement) {
172 $D('VNC_mouse_buttons').style.display = "inline";
173 UI.setMouseButton();
174 }
175
91308399
JM
176},
177
da6dd893
JM
178// Read form control compatible setting from cookie
179getSetting: function(name) {
e4671910 180 var val, ctrl = $D('VNC_' + name);
8d5d2c82 181 val = WebUtil.readCookie(name);
da6dd893
JM
182 if (ctrl.type === 'checkbox') {
183 if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
184 val = false;
185 } else {
186 val = true;
187 }
188 }
189 return val;
190},
191
192// Update cookie and form control setting. If value is not set, then
193// updates from control to current cookie setting.
194updateSetting: function(name, value) {
e4671910 195 var i, ctrl = $D('VNC_' + name);
da6dd893
JM
196 // Save the cookie for this session
197 if (typeof value !== 'undefined') {
8d5d2c82 198 WebUtil.createCookie(name, value);
da6dd893
JM
199 }
200
201 // Update the settings control
f7ec5b2c 202 value = UI.getSetting(name);
da6dd893
JM
203 if (ctrl.type === 'checkbox') {
204 ctrl.checked = value;
205 } else if (typeof ctrl.options !== 'undefined') {
8db09746 206 for (i = 0; i < ctrl.options.length; i += 1) {
da6dd893
JM
207 if (ctrl.options[i].value === value) {
208 ctrl.selectedIndex = i;
209 break;
210 }
211 }
212 } else {
213 ctrl.value = value;
214 }
215},
216
217// Save control setting to cookie
218saveSetting: function(name) {
e4671910 219 var val, ctrl = $D('VNC_' + name);
da6dd893
JM
220 if (ctrl.type === 'checkbox') {
221 val = ctrl.checked;
222 } else if (typeof ctrl.options !== 'undefined') {
223 val = ctrl.options[ctrl.selectedIndex].value;
224 } else {
225 val = ctrl.value;
226 }
8d5d2c82 227 WebUtil.createCookie(name, val);
8db09746 228 //Util.Debug("Setting saved '" + name + "=" + val + "'");
da6dd893
JM
229 return val;
230},
231
232// Initial page load read/initialization of settings
233initSetting: function(name, defVal) {
a8edf9d8 234 var val;
da6dd893
JM
235
236 // Check Query string followed by cookie
8d5d2c82 237 val = WebUtil.getQueryVar(name);
da6dd893 238 if (val === null) {
8d5d2c82 239 val = WebUtil.readCookie(name, defVal);
da6dd893 240 }
f7ec5b2c 241 UI.updateSetting(name, val);
8db09746 242 //Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
da6dd893
JM
243 return val;
244},
245
246
247// Toggle the settings menu:
248// On open, settings are refreshed from saved cookies.
249// On close, settings are applied
250clickSettingsMenu: function() {
f7ec5b2c
JM
251 if (UI.settingsOpen) {
252 UI.settingsApply();
da6dd893 253
f7ec5b2c 254 UI.closeSettingsMenu();
da6dd893 255 } else {
f7ec5b2c
JM
256 UI.updateSetting('encrypt');
257 UI.updateSetting('true_color');
d890e864 258 if (UI.rfb.get_display().get_cursor_uri()) {
f7ec5b2c 259 UI.updateSetting('cursor');
da6dd893 260 } else {
f7ec5b2c 261 UI.updateSetting('cursor', false);
e4671910 262 $D('VNC_cursor').disabled = true;
da6dd893 263 }
f7ec5b2c
JM
264 UI.updateSetting('shared');
265 UI.updateSetting('connectTimeout');
266 UI.updateSetting('stylesheet');
267 UI.updateSetting('logging');
da6dd893 268
f7ec5b2c 269 UI.openSettingsMenu();
da6dd893
JM
270 }
271},
272
273// Open menu
274openSettingsMenu: function() {
e4671910 275 $D('VNC_settings_menu').style.display = "block";
f7ec5b2c 276 UI.settingsOpen = true;
da6dd893
JM
277},
278
279// Close menu (without applying settings)
280closeSettingsMenu: function() {
e4671910 281 $D('VNC_settings_menu').style.display = "none";
f7ec5b2c 282 UI.settingsOpen = false;
da6dd893
JM
283},
284
285// Disable/enable controls depending on connection state
b5087acc
JM
286settingsDisabled: function(disabled, rfb) {
287 //Util.Debug(">> settingsDisabled");
e4671910
JM
288 $D('VNC_encrypt').disabled = disabled;
289 $D('VNC_true_color').disabled = disabled;
d890e864 290 if (rfb && rfb.get_display() && rfb.get_display().get_cursor_uri()) {
e4671910 291 $D('VNC_cursor').disabled = disabled;
da6dd893 292 } else {
f7ec5b2c 293 UI.updateSetting('cursor', false);
e4671910 294 $D('VNC_cursor').disabled = true;
da6dd893 295 }
e4671910
JM
296 $D('VNC_shared').disabled = disabled;
297 $D('VNC_connectTimeout').disabled = disabled;
b5087acc 298 //Util.Debug("<< settingsDisabled");
da6dd893
JM
299},
300
301// Save/apply settings when 'Apply' button is pressed
302settingsApply: function() {
8db09746 303 //Util.Debug(">> settingsApply");
f7ec5b2c
JM
304 UI.saveSetting('encrypt');
305 UI.saveSetting('true_color');
d890e864 306 if (UI.rfb.get_display().get_cursor_uri()) {
f7ec5b2c 307 UI.saveSetting('cursor');
da6dd893 308 }
f7ec5b2c
JM
309 UI.saveSetting('shared');
310 UI.saveSetting('connectTimeout');
311 UI.saveSetting('stylesheet');
312 UI.saveSetting('logging');
da6dd893
JM
313
314 // Settings with immediate (non-connected related) effect
f7ec5b2c
JM
315 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
316 WebUtil.init_logging(UI.getSetting('logging'));
da6dd893 317
8db09746 318 //Util.Debug("<< settingsApply");
da6dd893
JM
319},
320
321
322
f00b1e37 323setPassword: function() {
e4671910 324 UI.rfb.sendPassword($D('VNC_password').value);
f00b1e37
JM
325 return false;
326},
327
63708ff5 328sendCtrlAltDel: function() {
f7ec5b2c 329 UI.rfb.sendCtrlAltDel();
63708ff5
JM
330},
331
ad3f7624
JM
332setMouseButton: function(num) {
333 var b, blist = [1,2,4], button,
334 mouse = UI.rfb.get_mouse();
335
336 if (typeof num === 'undefined') {
337 // Show the default
338 num = mouse.get_touchButton();
339 } else if (num === mouse.get_touchButton()) {
340 // Set all buttons off (no clicks)
341 mouse.set_touchButton(0);
342 num = 0;
343 } else {
344 // Turn on one button
345 mouse.set_touchButton(num);
346 }
347
348 for (b = 0; b < blist.length; b++) {
349 button = $D('VNC_mouse_button' + blist[b]);
350 if (blist[b] === num) {
351 button.style.backgroundColor = "black";
352 button.style.color = "lightgray";
353 } else {
354 button.style.backgroundColor = "";
355 button.style.color = "";
356 }
357 }
358
359},
360
8db09746 361updateState: function(rfb, state, oldstate, msg) {
a7a89626 362 var s, sb, c, cad, klass;
e4671910
JM
363 s = $D('VNC_status');
364 sb = $D('VNC_status_bar');
365 c = $D('VNC_connect_button');
366 cad = $D('sendCtrlAltDelButton');
91308399
JM
367 switch (state) {
368 case 'failed':
f00b1e37 369 case 'fatal':
91308399 370 c.disabled = true;
160fabf6 371 cad.disabled = true;
f7ec5b2c 372 UI.settingsDisabled(true, rfb);
91308399
JM
373 klass = "VNC_status_error";
374 break;
375 case 'normal':
376 c.value = "Disconnect";
f7ec5b2c 377 c.onclick = UI.disconnect;
91308399 378 c.disabled = false;
160fabf6 379 cad.disabled = false;
f7ec5b2c 380 UI.settingsDisabled(true, rfb);
91308399
JM
381 klass = "VNC_status_normal";
382 break;
383 case 'disconnected':
f00b1e37 384 case 'loaded':
91308399 385 c.value = "Connect";
f7ec5b2c 386 c.onclick = UI.connect;
91308399
JM
387
388 c.disabled = false;
160fabf6 389 cad.disabled = true;
f7ec5b2c 390 UI.settingsDisabled(false, rfb);
91308399
JM
391 klass = "VNC_status_normal";
392 break;
f00b1e37
JM
393 case 'password':
394 c.value = "Send Password";
f7ec5b2c 395 c.onclick = UI.setPassword;
f00b1e37
JM
396
397 c.disabled = false;
398 cad.disabled = true;
f7ec5b2c 399 UI.settingsDisabled(true, rfb);
f00b1e37
JM
400 klass = "VNC_status_warn";
401 break;
91308399
JM
402 default:
403 c.disabled = true;
160fabf6 404 cad.disabled = true;
f7ec5b2c 405 UI.settingsDisabled(true, rfb);
91308399
JM
406 klass = "VNC_status_warn";
407 break;
408 }
409
410 if (typeof(msg) !== 'undefined') {
411 s.setAttribute("class", klass);
63708ff5 412 sb.setAttribute("class", klass);
91308399
JM
413 s.innerHTML = msg;
414 }
415
416},
417
8db09746 418clipReceive: function(rfb, text) {
f7ec5b2c 419 Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
e4671910 420 $D('VNC_clipboard_text').value = text;
f7ec5b2c 421 Util.Debug("<< UI.clipReceive");
8db09746
JM
422},
423
424
91308399 425connect: function() {
f7ec5b2c 426 var host, port, password;
da6dd893 427
f7ec5b2c 428 UI.closeSettingsMenu();
da6dd893 429
e4671910
JM
430 host = $D('VNC_host').value;
431 port = $D('VNC_port').value;
432 password = $D('VNC_password').value;
91308399 433 if ((!host) || (!port)) {
63708ff5 434 throw("Must set host and port");
91308399
JM
435 }
436
f7ec5b2c
JM
437 UI.rfb.set_encrypt(UI.getSetting('encrypt'));
438 UI.rfb.set_true_color(UI.getSetting('true_color'));
439 UI.rfb.set_local_cursor(UI.getSetting('cursor'));
440 UI.rfb.set_shared(UI.getSetting('shared'));
441 UI.rfb.set_connectTimeout(UI.getSetting('connectTimeout'));
da6dd893 442
f7ec5b2c 443 UI.rfb.connect(host, port, password);
91308399
JM
444},
445
446disconnect: function() {
f7ec5b2c 447 UI.closeSettingsMenu();
da6dd893 448
f7ec5b2c 449 UI.rfb.disconnect();
91308399
JM
450},
451
d890e864 452displayBlur: function() {
d1bd5ec7
JM
453 UI.rfb.get_keyboard().set_focused(false);
454 UI.rfb.get_mouse().set_focused(false);
91308399
JM
455},
456
d890e864 457displayFocus: function() {
d1bd5ec7
JM
458 UI.rfb.get_keyboard().set_focused(true);
459 UI.rfb.get_mouse().set_focused(true);
91308399
JM
460},
461
462clipClear: function() {
e4671910 463 $D('VNC_clipboard_text').value = "";
f7ec5b2c 464 UI.rfb.clipboardPasteFrom("");
91308399
JM
465},
466
467clipSend: function() {
e4671910 468 var text = $D('VNC_clipboard_text').value;
f7ec5b2c
JM
469 Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
470 UI.rfb.clipboardPasteFrom(text);
471 Util.Debug("<< UI.clipSend");
91308399
JM
472}
473
63708ff5 474};