]> git.proxmox.com Git - mirror_novnc.git/blob - include/ui.js
Merge branch 'master' into mobile
[mirror_novnc.git] / include / ui.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2011 Joel Martin
4 * Licensed under LGPL-3 (see LICENSE.txt)
5 *
6 * See README.md for usage and integration instructions.
7 */
8
9 "use strict";
10 /*jslint white: false, browser: true */
11 /*global window, $D, Util, WebUtil, RFB, Display */
12
13 var UI = {
14
15 settingsOpen : false,
16 connSettingsOpen : true,
17 clipboardOpen: false,
18
19 // Render default UI and initialize settings menu
20 load: function() {
21 var html = '', i, sheet, sheets, llevels;
22
23 // Stylesheet selection dropdown
24 sheet = WebUtil.selectStylesheet();
25 sheets = WebUtil.getStylesheets();
26 for (i = 0; i < sheets.length; i += 1) {
27 UI.addOption($D('noVNC_stylesheet'),sheets[i].title, sheets[i].title);
28 }
29
30 // Logging selection dropdown
31 llevels = ['error', 'warn', 'info', 'debug'];
32 for (i = 0; i < llevels.length; i += 1) {
33 UI.addOption($D('noVNC_logging'),llevels[i], llevels[i]);
34 }
35
36 // Settings with immediate effects
37 UI.initSetting('logging', 'warn');
38 WebUtil.init_logging(UI.getSetting('logging'));
39 UI.initSetting('stylesheet', 'default');
40
41 WebUtil.selectStylesheet(null);
42 // call twice to get around webkit bug
43 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
44
45 /* Populate the controls if defaults are provided in the URL */
46 UI.initSetting('host', '');
47 UI.initSetting('port', '');
48 UI.initSetting('password', '');
49 UI.initSetting('encrypt', false);
50 UI.initSetting('true_color', true);
51 UI.initSetting('cursor', false);
52 UI.initSetting('shared', true);
53 UI.initSetting('connectTimeout', 2);
54
55 UI.rfb = RFB({'target': $D('noVNC_canvas'),
56 'onUpdateState': UI.updateState,
57 'onClipboard': UI.clipReceive});
58
59 // Unfocus clipboard when over the VNC area
60 //$D('VNC_screen').onmousemove = function () {
61 // var keyboard = UI.rfb.get_keyboard();
62 // if ((! keyboard) || (! keyboard.get_focused())) {
63 // $D('VNC_clipboard_text').blur();
64 // }
65 // };
66
67 // Show mouse selector buttons on touch screen devices
68 if ('ontouchstart' in document.documentElement) {
69 $D('noVNC_mobile_buttons').style.display = "inline";
70 UI.setMouseButton();
71 window.scrollTo(0, 1);
72 }
73
74 //iOS Safari does not support CSS position:fixed.
75 //This detects iOS devices and enables javascript workaround.
76 if ((navigator.userAgent.match(/iPhone/i)) ||
77 (navigator.userAgent.match(/iPod/i)) ||
78 (navigator.userAgent.match(/iPad/i))) {
79 UI.setOnscroll();
80 UI.setResize();
81 }
82
83 $D('noVNC_host').focus();
84 },
85
86 // Read form control compatible setting from cookie
87 getSetting: function(name) {
88 var val, ctrl = $D('noVNC_' + name);
89 val = WebUtil.readCookie(name);
90 if (ctrl.type === 'checkbox') {
91 if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
92 val = false;
93 } else {
94 val = true;
95 }
96 }
97 return val;
98 },
99
100 // Update cookie and form control setting. If value is not set, then
101 // updates from control to current cookie setting.
102 updateSetting: function(name, value) {
103
104 var i, ctrl = $D('noVNC_' + name);
105 // Save the cookie for this session
106 if (typeof value !== 'undefined') {
107 WebUtil.createCookie(name, value);
108 }
109
110 // Update the settings control
111 value = UI.getSetting(name);
112
113 if (ctrl.type === 'checkbox') {
114 ctrl.checked = value;
115
116 } else if (typeof ctrl.options !== 'undefined') {
117 for (i = 0; i < ctrl.options.length; i += 1) {
118 if (ctrl.options[i].value === value) {
119 ctrl.selectedIndex = i;
120 break;
121 }
122 }
123 } else {
124 /*Weird IE9 error leads to 'null' appearring
125 in textboxes instead of ''.*/
126 if (value === null) {
127 value = "";
128 }
129 ctrl.value = value;
130 }
131 },
132
133 // Save control setting to cookie
134 saveSetting: function(name) {
135 var val, ctrl = $D('noVNC_' + name);
136 if (ctrl.type === 'checkbox') {
137 val = ctrl.checked;
138 } else if (typeof ctrl.options !== 'undefined') {
139 val = ctrl.options[ctrl.selectedIndex].value;
140 } else {
141 val = ctrl.value;
142 }
143 WebUtil.createCookie(name, val);
144 //Util.Debug("Setting saved '" + name + "=" + val + "'");
145 return val;
146 },
147
148 // Initial page load read/initialization of settings
149 initSetting: function(name, defVal) {
150 var val;
151
152 // Check Query string followed by cookie
153 val = WebUtil.getQueryVar(name);
154 if (val === null) {
155 val = WebUtil.readCookie(name, defVal);
156 }
157 UI.updateSetting(name, val);
158 //Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
159 return val;
160 },
161
162
163 // Toggle the settings menu:
164 // On open, settings are refreshed from saved cookies.
165 // On close, settings are applied
166 clickSettingsMenu: function() {
167 if (UI.settingsOpen) {
168 UI.settingsApply();
169
170 UI.closeSettingsMenu();
171 } else {
172 UI.updateSetting('encrypt');
173 UI.updateSetting('true_color');
174 if (UI.rfb.get_display().get_cursor_uri()) {
175 UI.updateSetting('cursor');
176 } else {
177 UI.updateSetting('cursor', false);
178 $D('noVNC_cursor').disabled = true;
179 }
180 UI.updateSetting('shared');
181 UI.updateSetting('connectTimeout');
182 UI.updateSetting('stylesheet');
183 UI.updateSetting('logging');
184
185 UI.openSettingsMenu();
186 }
187 },
188
189 // Open menu
190 openSettingsMenu: function() {
191 if (UI.clipboardOpen == true) {
192 UI.showClipboard();
193 }
194 //Close connection settings if open
195 if (UI.connSettingsOpen == true) {
196 UI.connectPanelbutton();
197 }
198 $D('noVNC_Settings').style.display = "block";
199 UI.settingsOpen = true;
200 },
201
202 // Close menu (without applying settings)
203 closeSettingsMenu: function() {
204 $D('noVNC_Settings').style.display = "none";
205 UI.settingsOpen = false;
206 },
207
208 // Disable/enable controls depending on connection state
209 settingsDisabled: function(disabled, rfb) {
210 //Util.Debug(">> settingsDisabled");
211 $D('noVNC_encrypt').disabled = disabled;
212 $D('noVNC_true_color').disabled = disabled;
213 if (rfb && rfb.get_display() && rfb.get_display().get_cursor_uri()) {
214 $D('noVNC_cursor').disabled = disabled;
215 } else {
216 UI.updateSetting('cursor', false);
217 $D('noVNC_cursor').disabled = true;
218 }
219 $D('noVNC_shared').disabled = disabled;
220 $D('noVNC_connectTimeout').disabled = disabled;
221 //Util.Debug("<< settingsDisabled");
222 },
223
224 // Save/apply settings when 'Apply' button is pressed
225 settingsApply: function() {
226 //Util.Debug(">> settingsApply");
227 UI.saveSetting('encrypt');
228 UI.saveSetting('true_color');
229 if (UI.rfb.get_display().get_cursor_uri()) {
230 UI.saveSetting('cursor');
231 }
232 UI.saveSetting('shared');
233 UI.saveSetting('connectTimeout');
234 UI.saveSetting('stylesheet');
235 UI.saveSetting('logging');
236
237 // Settings with immediate (non-connected related) effect
238 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
239 WebUtil.init_logging(UI.getSetting('logging'));
240 //Util.Debug("<< settingsApply");
241 },
242
243
244
245 setPassword: function() {
246 UI.rfb.sendPassword($D('noVNC_password').value);
247 //Reset connect button.
248 $D('noVNC_connect_button').value = "Connect";
249 $D('noVNC_connect_button').onclick = UI.Connect;
250 //Hide connection panel.
251 UI.connectPanelbutton();
252 return false;
253 },
254
255 sendCtrlAltDel: function() {
256 UI.rfb.sendCtrlAltDel();
257 },
258
259 setMouseButton: function(num) {
260 var b, blist = [1,2,4], button,
261 mouse = UI.rfb.get_mouse();
262
263 if (typeof num === 'undefined') {
264 // Show the default
265 num = mouse.get_touchButton();
266 } else if (num === mouse.get_touchButton()) {
267 // Set all buttons off (no clicks)
268 mouse.set_touchButton(0);
269 num = 0;
270 } else {
271 // Turn on one button
272 mouse.set_touchButton(num);
273 }
274
275 for (b = 0; b < blist.length; b++) {
276 button = $D('noVNC_mouse_button' + blist[b]);
277 if (blist[b] === num) {
278 button.style.backgroundColor = "black";
279 button.style.color = "lightgray";
280 } else {
281 button.style.backgroundColor = "";
282 button.style.color = "";
283 }
284 }
285 },
286
287 updateState: function(rfb, state, oldstate, msg) {
288 var s, sb, c, cad, klass;
289 s = $D('noVNC_status');
290 sb = $D('noVNC_status_bar');
291 c = $D('connectPanelbutton');
292 cad = $D('sendCtrlAltDelButton');
293 switch (state) {
294 case 'failed':
295 case 'fatal':
296 c.disabled = true;
297 cad.style.display = "none";
298 UI.settingsDisabled(true, rfb);
299 klass = "noVNC_status_error";
300 break;
301 case 'normal':
302 c.value = "Disconnect";
303 c.onclick = UI.disconnect;
304 c.disabled = false;
305 cad.style.display = "block";
306 UI.settingsDisabled(true, rfb);
307 klass = "noVNC_status_normal";
308 break;
309 case 'disconnected':
310 $D('noVNC_logo').style.display = "block";
311 c.value = "Connection";
312 c.onclick = UI.connectPanelbutton;
313 case 'loaded':
314 c.value = "Connection";
315 c.onclick = UI.connectPanelbutton;
316 c.disabled = false;
317 cad.style.display = "none";
318 UI.settingsDisabled(false, rfb);
319 klass = "noVNC_status_normal";
320 break;
321 case 'password':
322 UI.connectPanelbutton();
323
324 $D('noVNC_connect_button').value = "Send Password";
325 $D('noVNC_connect_button').onclick = UI.setPassword;
326 $D('noVNC_password').focus();
327
328 c.disabled = false;
329 cad.style.display = "none";
330 UI.settingsDisabled(true, rfb);
331 klass = "noVNC_status_warn";
332 break;
333 default:
334 c.disabled = true;
335 cad.style.display = "none";
336 UI.settingsDisabled(true, rfb);
337 klass = "noVNC_status_warn";
338 break;
339 }
340
341 if (typeof(msg) !== 'undefined') {
342 s.setAttribute("class", klass);
343 sb.setAttribute("class", klass);
344 s.innerHTML = msg;
345 }
346
347 },
348
349 clipReceive: function(rfb, text) {
350 Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
351 $D('noVNC_clipboard_text').value = text;
352 Util.Debug("<< UI.clipReceive");
353 },
354
355
356 connect: function() {
357 var host, port, password;
358
359 UI.closeSettingsMenu();
360 UI.connectPanelbutton();
361
362 host = $D('noVNC_host').value;
363 port = $D('noVNC_port').value;
364 password = $D('noVNC_password').value;
365 if ((!host) || (!port)) {
366 throw("Must set host and port");
367 }
368
369 UI.rfb.set_encrypt(UI.getSetting('encrypt'));
370 UI.rfb.set_true_color(UI.getSetting('true_color'));
371 UI.rfb.set_local_cursor(UI.getSetting('cursor'));
372 UI.rfb.set_shared(UI.getSetting('shared'));
373 UI.rfb.set_connectTimeout(UI.getSetting('connectTimeout'));
374
375 UI.rfb.connect(host, port, password);
376 //Close dialog.
377 setTimeout(UI.setBarPosition, 100);
378 $D('noVNC_logo').style.display = "none";
379 },
380
381 disconnect: function() {
382 UI.closeSettingsMenu();
383 UI.rfb.disconnect();
384
385 $D('noVNC_logo').style.display = "block";
386 UI.connSettingsOpen = false;
387 UI.connectPanelbutton();
388 },
389
390 displayBlur: function() {
391 UI.rfb.get_keyboard().set_focused(false);
392 UI.rfb.get_mouse().set_focused(false);
393 },
394
395 displayFocus: function() {
396 UI.rfb.get_keyboard().set_focused(true);
397 UI.rfb.get_mouse().set_focused(true);
398 },
399
400 clipClear: function() {
401 $D('noVNC_clipboard_text').value = "";
402 UI.rfb.clipboardPasteFrom("");
403 },
404
405 clipSend: function() {
406 var text = $D('noVNC_clipboard_text').value;
407 Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
408 UI.rfb.clipboardPasteFrom(text);
409 Util.Debug("<< UI.clipSend");
410 },
411
412 showClipboard: function() {
413 //Close settings if open
414 if (UI.settingsOpen == true) {
415 UI.closeSettingsMenu();
416 }
417 //Close connection settings if open
418 if (UI.connSettingsOpen == true) {
419 UI.connectPanelbutton();
420 }
421 //Toggle Connection Panel
422 if (UI.clipboardOpen == true) {
423 $D('noVNC_clipboard').style.display = "none";
424 UI.clipboardOpen = false;
425 } else {
426 $D('noVNC_clipboard').style.display = "block";
427 UI.clipboardOpen = true;
428 }
429 },
430
431
432 showKeyboard: function() {
433 //Get Current Scroll Position
434 var scrollx =
435 (document.all)?document.body.scrollLeft:window.pageXOffset;
436 var scrolly =
437 (document.all)?document.body.scrollTop:window.pageYOffset;
438
439 //Stop browser zooming on textbox.
440 UI.zoomDisable();
441 $D('keyboardinput').focus();
442 scroll(scrollx,scrolly);
443 //Renable user zoom.
444 UI.zoomEnable();
445 },
446
447 zoomDisable: function() {
448 //Change viewport meta data to disable zooming.
449 UI.changeViewportMeta("user-scalable=0");
450 },
451
452 zoomEnable: function(){
453 //Change viewport meta data to enable user zooming.
454 UI.changeViewportMeta("user-scalable=1");
455 },
456
457 changeViewportMeta: function (newattributes) {
458
459 // First, get the array of meta-tag elements
460 var metatags = document.getElementsByTagName("meta");
461
462 // Update only the Viewport meta tag
463 for (var cnt = 0; cnt < metatags.length; cnt++)
464 {
465 var name = metatags[cnt].getAttribute("name");
466 var content = metatags[cnt].getAttribute("content");
467
468 // Update the Viewport meta tag
469 if (metatags[cnt].getAttribute("name") == "viewport") {
470 metatags[cnt].setAttribute("content", newattributes);
471 }
472 }
473 },
474
475 //iOS < Version 5 does not support position fixed. Javascript workaround:
476 setOnscroll: function() {
477 window.onscroll = function() {
478 UI.setBarPosition();
479 };
480 },
481
482 setResize: function () {
483 window.onResize = function() {
484 UI.setBarPosition();
485 };
486 },
487
488 //Helper to add options to dropdown.
489 addOption: function(selectbox,text,value )
490 {
491 var optn = document.createElement("OPTION");
492 optn.text = text;
493 optn.value = value;
494 selectbox.options.add(optn);
495 },
496
497 setBarPosition: function() {
498 $D('noVNC-control-bar').style.top = (window.pageYOffset) + 'px';
499 $D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px';
500 $D('noVNC_buttons_right').style.right = 0 + 'px';
501
502 var vncwidth = $D('noVNC_screen').style.offsetWidth;
503 $D('noVNC-control-bar').style.width = vncwidth + 'px';
504 },
505
506 connectPanelbutton: function() {
507 //Close connection settings if open
508 if (UI.settingsOpen == true) {
509 UI.closeSettingsMenu();
510 }
511 if (UI.clipboardOpen == true) {
512 UI.showClipboard();
513 }
514
515 //Toggle Connection Panel
516 if (UI.connSettingsOpen == true) {
517 $D('noVNC_controls').style.display = "none";
518 UI.connSettingsOpen = false;
519 } else {
520 $D('noVNC_controls').style.display = "block";
521 UI.connSettingsOpen = true;
522 $D('noVNC_host').focus();
523 }
524 }
525
526 };
527
528
529
530