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