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