]> git.proxmox.com Git - mirror_novnc.git/blob - include/ui.js
Modifed UI. Move HTML from ui.js to vnc.html.
[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 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 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); // call twice to get around webkit bug
42 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
43
44 /* Populate the controls if defaults are provided in the URL */
45 UI.initSetting('host', '');
46 UI.initSetting('port', '');
47 UI.initSetting('password', '');
48 UI.initSetting('encrypt', false);
49 UI.initSetting('true_color', true);
50 UI.initSetting('cursor', false);
51 UI.initSetting('shared', true);
52 UI.initSetting('connectTimeout', 2);
53
54 UI.rfb = RFB({'target': $D('noVNC_canvas'),
55 'onUpdateState': UI.updateState,
56 'onClipboard': UI.clipReceive});
57
58 // Unfocus clipboard when over the VNC area
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
66 // Show mouse selector buttons on touch screen devices
67 if ('ontouchstart' in document.documentElement) {
68 $D('noVNC_mobile_buttons').style.display = "inline";
69 UI.setMouseButton();
70 window.scrollTo(0, 1);
71 }
72
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
80 },
81
82 // Read form control compatible setting from cookie
83 getSetting: function(name) {
84 var val, ctrl = $D('noVNC_' + name);
85 val = WebUtil.readCookie(name);
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.
98 updateSetting: function(name, value) {
99
100 var i, ctrl = $D('noVNC_' + name);
101 // Save the cookie for this session
102 if (typeof value !== 'undefined') {
103 WebUtil.createCookie(name, value);
104 }
105 if(name === 'host')
106 {
107
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 in textboxes instead of ''.*/
125 if(value === null)
126 {
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 {
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";
200 UI.settingsOpen = true;
201 },
202
203 // Close menu (without applying settings)
204 closeSettingsMenu: function() {
205 $D('noVNC_Settings').style.display = "none";
206 UI.settingsOpen = false;
207 },
208
209 // Disable/enable controls depending on connection state
210 settingsDisabled: function(disabled, rfb) {
211 //Util.Debug(">> settingsDisabled");
212 $D('noVNC_encrypt').disabled = disabled;
213 $D('noVNC_true_color').disabled = disabled;
214 if (rfb && rfb.get_display() && rfb.get_display().get_cursor_uri()) {
215 $D('noVNC_cursor').disabled = disabled;
216 } else {
217 UI.updateSetting('cursor', false);
218 $D('noVNC_cursor').disabled = true;
219 }
220 $D('noVNC_shared').disabled = disabled;
221 $D('noVNC_connectTimeout').disabled = disabled;
222 //Util.Debug("<< settingsDisabled");
223 },
224
225 // Save/apply settings when 'Apply' button is pressed
226 settingsApply: function() {
227 //Util.Debug(">> settingsApply");
228 UI.saveSetting('encrypt');
229 UI.saveSetting('true_color');
230 if (UI.rfb.get_display().get_cursor_uri()) {
231 UI.saveSetting('cursor');
232 }
233 UI.saveSetting('shared');
234 UI.saveSetting('connectTimeout');
235 UI.saveSetting('stylesheet');
236 UI.saveSetting('logging');
237
238 // Settings with immediate (non-connected related) effect
239 WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
240 WebUtil.init_logging(UI.getSetting('logging'));
241 //Util.Debug("<< settingsApply");
242 },
243
244
245
246 setPassword: function() {
247 UI.rfb.sendPassword($D('noVNC_password').value);
248 return false;
249 },
250
251 sendCtrlAltDel: function() {
252 UI.rfb.sendCtrlAltDel();
253 },
254
255 setMouseButton: 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++) {
272 button = $D('noVNC_mouse_button' + blist[b]);
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 }
281 },
282
283 updateState: function(rfb, state, oldstate, msg) {
284 var s, sb, c, cad, klass;
285 s = $D('noVNC_status');
286 sb = $D('noVNC_status_bar');
287 c = $D('noVNC_connect_button');
288 cad = $D('sendCtrlAltDelButton');
289 switch (state) {
290 case 'failed':
291 case 'fatal':
292 c.disabled = true;
293 cad.disabled = true;
294 UI.settingsDisabled(true, rfb);
295 klass = "noVNC_status_error";
296 break;
297 case 'normal':
298 c.value = "Disconnect";
299 c.onclick = UI.disconnect;
300 c.disabled = false;
301 cad.disabled = false;
302 UI.settingsDisabled(true, rfb);
303 klass = "noVNC_status_normal";
304 break;
305 case 'disconnected':
306 $D('noVNC_defaultScreen').style.display = "block";
307 case 'loaded':
308 c.value = "Connect";
309 c.onclick = UI.connect;
310
311 c.disabled = false;
312 cad.disabled = true;
313 UI.settingsDisabled(false, rfb);
314 klass = "noVNC_status_normal";
315 break;
316 case 'password':
317 c.value = "Send Password";
318 c.onclick = UI.setPassword;
319
320 c.disabled = false;
321 cad.disabled = true;
322 UI.settingsDisabled(true, rfb);
323 klass = "noVNC_status_warn";
324 break;
325 default:
326 c.disabled = true;
327 cad.disabled = true;
328 UI.settingsDisabled(true, rfb);
329 klass = "noVNC_status_warn";
330 break;
331 }
332
333 if (typeof(msg) !== 'undefined') {
334 s.setAttribute("class", klass);
335 sb.setAttribute("class", klass);
336 s.innerHTML = msg;
337 }
338
339 },
340
341 clipReceive: function(rfb, text) {
342 Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
343 $D('noVNC_clipboard_text').value = text;
344 Util.Debug("<< UI.clipReceive");
345 },
346
347
348 connect: function() {
349 var host, port, password;
350
351 UI.closeSettingsMenu();
352 connectPanelbutton();
353 host = $D('noVNC_host').value;
354 port = $D('noVNC_port').value;
355 password = $D('noVNC_password').value;
356 if ((!host) || (!port)) {
357 throw("Must set host and port");
358 }
359
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'));
365
366 UI.rfb.connect(host, port, password);
367 //Close dialog.
368 setTimeout("setBarPosition()",100);
369 $D('noVNC_defaultScreen').style.display = "none";
370 },
371
372 disconnect: function() {
373 UI.closeSettingsMenu();
374 UI.rfb.disconnect();
375 $D('noVNC_defaultScreen').style.display = "block";
376 UI.openSettingsMenu();
377 },
378
379 displayBlur: function() {
380 UI.rfb.get_keyboard().set_focused(false);
381 UI.rfb.get_mouse().set_focused(false);
382 },
383
384 displayFocus: function() {
385 UI.rfb.get_keyboard().set_focused(true);
386 UI.rfb.get_mouse().set_focused(true);
387 },
388
389 clipClear: function() {
390 $D('noVNC_clipboard_text').value = "";
391 UI.rfb.clipboardPasteFrom("");
392 },
393
394 clipSend: function() {
395 var text = $D('noVNC_clipboard_text').value;
396 Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
397 UI.rfb.clipboardPasteFrom(text);
398 Util.Debug("<< UI.clipSend");
399 },
400
401 showClipboard: 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 }
418 }
419
420 };
421
422 function 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 }
442
443 function showkeyboard(){
444 //Get Current Scroll Position
445 var scrollx = (document.all)?document.body.scrollLeft:window.pageXOffset;
446 var scrolly = (document.all)?document.body.scrollTop:window.pageYOffset;
447
448
449 //Stop browser zooming on textbox.
450 zoomDisable();
451 $D('keyboardinput').focus();
452 scroll(scrollx,scrolly);
453 //Renable user zoom.
454 zoomEnable();
455 }
456
457 function zoomDisable(){
458 //Change viewport meta data to disable zooming.
459 changeViewportMeta("user-scalable=0");
460 }
461
462 function zoomEnable(){
463 //Change viewport meta data to enable user zooming.
464 changeViewportMeta("user-scalable=1");
465 }
466
467 function 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 }
483 }
484
485 //iOS < Version 5 does not support position fixed. Javascript workaround:
486 function setOnscroll() {
487 window.onscroll = function() {
488 setBarPosition();
489 };
490 }
491
492 function setResize() {
493 window.onResize = function() {
494 setBarPosition();
495 };
496 }
497
498 function 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.
509 function 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 }