]>
git.proxmox.com Git - mirror_novnc.git/blob - include/ui.js
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2011 Joel Martin
4 * Licensed under LGPL-3 (see LICENSE.txt)
6 * See README.md for usage and integration instructions.
10 /*jslint white: false, browser: true */
11 /*global window, $D, Util, WebUtil, RFB, Display */
17 // Render default UI and initialize settings menu
18 load: function(target
) {
19 var html
= '', i
, sheet
, sheets
, llevels
;
21 /* Populate the 'target' DOM element with default UI */
24 } else if (typeof target
=== 'string') {
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>';
39 target
.innerHTML
= html
;
43 html
+= '<div id="VNC_controls">';
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>';
49 html
+= ' <li><input id="VNC_connect_button" type="button"';
50 html
+= ' value="Loading" disabled></li>';
53 html
+= '<div id="VNC_screen">';
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>';
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
+= ' <input type="button" id="showKeyboard" onclick="showkeyboard()" value="Keyboard" />';
68 html
+= ' </span></nobr></div></td>';
70 // Settings drop-down menu
71 html
+= ' <td width=1%><div class="VNC_buttons_right">';
72 html
+= ' <input type=button class="VNC_status_button" value="Settings"';
73 html
+= ' id="menuButton"';
74 html
+= ' onclick="UI.clickSettingsMenu();">';
75 html
+= ' <span id="VNC_settings_menu"';
76 html
+= ' onmouseover="UI.displayBlur();"';
77 html
+= ' onmouseout="UI.displayFocus();">';
79 html
+= ' <li><input id="VNC_encrypt"';
80 html
+= ' type="checkbox"> Encrypt</li>';
81 html
+= ' <li><input id="VNC_true_color"';
82 html
+= ' type="checkbox" checked> True Color</li>';
83 html
+= ' <li><input id="VNC_cursor"';
84 html
+= ' type="checkbox"> Local Cursor</li>';
85 html
+= ' <li><input id="VNC_shared"';
86 html
+= ' type="checkbox"> Shared Mode</li>';
87 html
+= ' <li><input id="VNC_connectTimeout"';
88 html
+= ' type="input"> Connect Timeout (s)</li>';
91 // Stylesheet selection dropdown
92 html
+= ' <li><select id="VNC_stylesheet" name="vncStyle">';
93 html
+= ' <option value="default">default</option>';
94 sheet
= WebUtil
.selectStylesheet();
95 sheets
= WebUtil
.getStylesheets();
96 for (i
= 0; i
< sheets
.length
; i
+= 1) {
97 html
+= '<option value="' + sheets
[i
].title
+ '">' + sheets
[i
].title
+ '</option>';
99 html
+= ' </select> Style</li>';
101 // Logging selection dropdown
102 html
+= ' <li><select id="VNC_logging" name="vncLogging">';
103 llevels
= ['error', 'warn', 'info', 'debug'];
104 for (i
= 0; i
< llevels
.length
; i
+= 1) {
105 html
+= '<option value="' + llevels
[i
] + '">' + llevels
[i
] + '</option>';
107 html
+= ' </select> Logging</li>';
110 html
+= ' <li><input type="button" id="VNC_apply" value="Apply"';
111 html
+= ' onclick="UI.settingsApply()"></li>';
113 html
+= ' </span></div></td>';
116 html
+= ' <td width=1%><div class="VNC_buttons_right">';
117 html
+= ' <input type=button class="VNC_status_button" value="CtrlAltDel"';
118 html
+= ' id="sendCtrlAltDelButton"';
119 html
+= ' onclick="UI.sendCtrlAltDel();"></div></td>';
121 html
+= ' </tr></table>';
123 html
+= ' <canvas id="VNC_canvas" width="640px" height="20px">';
124 html
+= ' Canvas not supported.';
125 html
+= ' </canvas>';
126 html
+= '<input id="keyboardinput" style="border:none;" type="text" onKeyDown="onKeyDown(event);"/>';
129 html
+= '<div id="VNC_clipboard">';
130 html
+= ' VNC Clipboard:';
131 html
+= ' <input id="VNC_clipboard_clear_button"';
132 html
+= ' type="button" value="Clear"';
133 html
+= ' onclick="UI.clipClear();">';
135 html
+= ' <textarea id="VNC_clipboard_text" cols=80 rows=5';
136 html
+= ' onfocus="UI.displayBlur();"';
137 html
+= ' onblur="UI.displayFocus();"';
138 html
+= ' onchange="UI.clipSend();"></textarea>';
140 target
.innerHTML
= html
;
142 // Settings with immediate effects
143 UI
.initSetting('logging', 'warn');
144 WebUtil
.init_logging(UI
.getSetting('logging'));
145 UI
.initSetting('stylesheet', 'default');
147 WebUtil
.selectStylesheet(null); // call twice to get around webkit bug
148 WebUtil
.selectStylesheet(UI
.getSetting('stylesheet'));
150 /* Populate the controls if defaults are provided in the URL */
151 UI
.initSetting('host', '');
152 UI
.initSetting('port', '');
153 UI
.initSetting('password', '');
154 UI
.initSetting('encrypt', false);
155 UI
.initSetting('true_color', true);
156 UI
.initSetting('cursor', false);
157 UI
.initSetting('shared', true);
158 UI
.initSetting('connectTimeout', 2);
160 UI
.rfb
= RFB({'target': $D('VNC_canvas'),
161 'onUpdateState': UI
.updateState
,
162 'onClipboard': UI
.clipReceive
});
164 // Unfocus clipboard when over the VNC area
165 $D('VNC_screen').onmousemove = function () {
166 var keyboard
= UI
.rfb
.get_keyboard();
167 if ((! keyboard
) || (! keyboard
.get_focused())) {
168 $D('VNC_clipboard_text').blur();
172 // Show mouse selector buttons on touch screen devices
173 if ('ontouchstart' in document
.documentElement
) {
174 $D('VNC_mouse_buttons').style
.display
= "inline";
180 // Read form control compatible setting from cookie
181 getSetting: function(name
) {
182 var val
, ctrl
= $D('VNC_' + name
);
183 val
= WebUtil
.readCookie(name
);
184 if (ctrl
.type
=== 'checkbox') {
185 if (val
.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
194 // Update cookie and form control setting. If value is not set, then
195 // updates from control to current cookie setting.
196 updateSetting: function(name
, value
) {
197 var i
, ctrl
= $D('VNC_' + name
);
198 // Save the cookie for this session
199 if (typeof value
!== 'undefined') {
200 WebUtil
.createCookie(name
, value
);
203 // Update the settings control
204 value
= UI
.getSetting(name
);
205 if (ctrl
.type
=== 'checkbox') {
206 ctrl
.checked
= value
;
207 } else if (typeof ctrl
.options
!== 'undefined') {
208 for (i
= 0; i
< ctrl
.options
.length
; i
+= 1) {
209 if (ctrl
.options
[i
].value
=== value
) {
210 ctrl
.selectedIndex
= i
;
219 // Save control setting to cookie
220 saveSetting: function(name
) {
221 var val
, ctrl
= $D('VNC_' + name
);
222 if (ctrl
.type
=== 'checkbox') {
224 } else if (typeof ctrl
.options
!== 'undefined') {
225 val
= ctrl
.options
[ctrl
.selectedIndex
].value
;
229 WebUtil
.createCookie(name
, val
);
230 //Util.Debug("Setting saved '" + name + "=" + val + "'");
234 // Initial page load read/initialization of settings
235 initSetting: function(name
, defVal
) {
238 // Check Query string followed by cookie
239 val
= WebUtil
.getQueryVar(name
);
241 val
= WebUtil
.readCookie(name
, defVal
);
243 UI
.updateSetting(name
, val
);
244 //Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
249 // Toggle the settings menu:
250 // On open, settings are refreshed from saved cookies.
251 // On close, settings are applied
252 clickSettingsMenu: function() {
253 if (UI
.settingsOpen
) {
256 UI
.closeSettingsMenu();
258 UI
.updateSetting('encrypt');
259 UI
.updateSetting('true_color');
260 if (UI
.rfb
.get_display().get_cursor_uri()) {
261 UI
.updateSetting('cursor');
263 UI
.updateSetting('cursor', false);
264 $D('VNC_cursor').disabled
= true;
266 UI
.updateSetting('shared');
267 UI
.updateSetting('connectTimeout');
268 UI
.updateSetting('stylesheet');
269 UI
.updateSetting('logging');
271 UI
.openSettingsMenu();
276 openSettingsMenu: function() {
277 $D('VNC_settings_menu').style
.display
= "block";
278 UI
.settingsOpen
= true;
281 // Close menu (without applying settings)
282 closeSettingsMenu: function() {
283 $D('VNC_settings_menu').style
.display
= "none";
284 UI
.settingsOpen
= false;
287 // Disable/enable controls depending on connection state
288 settingsDisabled: function(disabled
, rfb
) {
289 //Util.Debug(">> settingsDisabled");
290 $D('VNC_encrypt').disabled
= disabled
;
291 $D('VNC_true_color').disabled
= disabled
;
292 if (rfb
&& rfb
.get_display() && rfb
.get_display().get_cursor_uri()) {
293 $D('VNC_cursor').disabled
= disabled
;
295 UI
.updateSetting('cursor', false);
296 $D('VNC_cursor').disabled
= true;
298 $D('VNC_shared').disabled
= disabled
;
299 $D('VNC_connectTimeout').disabled
= disabled
;
300 //Util.Debug("<< settingsDisabled");
303 // Save/apply settings when 'Apply' button is pressed
304 settingsApply: function() {
305 //Util.Debug(">> settingsApply");
306 UI
.saveSetting('encrypt');
307 UI
.saveSetting('true_color');
308 if (UI
.rfb
.get_display().get_cursor_uri()) {
309 UI
.saveSetting('cursor');
311 UI
.saveSetting('shared');
312 UI
.saveSetting('connectTimeout');
313 UI
.saveSetting('stylesheet');
314 UI
.saveSetting('logging');
316 // Settings with immediate (non-connected related) effect
317 WebUtil
.selectStylesheet(UI
.getSetting('stylesheet'));
318 WebUtil
.init_logging(UI
.getSetting('logging'));
320 //Util.Debug("<< settingsApply");
325 setPassword: function() {
326 UI
.rfb
.sendPassword($D('VNC_password').value
);
330 sendCtrlAltDel: function() {
331 UI
.rfb
.sendCtrlAltDel();
334 setMouseButton: function(num
) {
335 var b
, blist
= [1,2,4], button
,
336 mouse
= UI
.rfb
.get_mouse();
338 if (typeof num
=== 'undefined') {
340 num
= mouse
.get_touchButton();
341 } else if (num
=== mouse
.get_touchButton()) {
342 // Set all buttons off (no clicks)
343 mouse
.set_touchButton(0);
346 // Turn on one button
347 mouse
.set_touchButton(num
);
350 for (b
= 0; b
< blist
.length
; b
++) {
351 button
= $D('VNC_mouse_button' + blist
[b
]);
352 if (blist
[b
] === num
) {
353 button
.style
.backgroundColor
= "black";
354 button
.style
.color
= "lightgray";
356 button
.style
.backgroundColor
= "";
357 button
.style
.color
= "";
363 updateState: function(rfb
, state
, oldstate
, msg
) {
364 var s
, sb
, c
, cad
, klass
;
365 s
= $D('VNC_status');
366 sb
= $D('VNC_status_bar');
367 c
= $D('VNC_connect_button');
368 cad
= $D('sendCtrlAltDelButton');
374 UI
.settingsDisabled(true, rfb
);
375 klass
= "VNC_status_error";
378 c
.value
= "Disconnect";
379 c
.onclick
= UI
.disconnect
;
381 cad
.disabled
= false;
382 UI
.settingsDisabled(true, rfb
);
383 klass
= "VNC_status_normal";
388 c
.onclick
= UI
.connect
;
392 UI
.settingsDisabled(false, rfb
);
393 klass
= "VNC_status_normal";
396 c
.value
= "Send Password";
397 c
.onclick
= UI
.setPassword
;
401 UI
.settingsDisabled(true, rfb
);
402 klass
= "VNC_status_warn";
407 UI
.settingsDisabled(true, rfb
);
408 klass
= "VNC_status_warn";
412 if (typeof(msg
) !== 'undefined') {
413 s
.setAttribute("class", klass
);
414 sb
.setAttribute("class", klass
);
420 clipReceive: function(rfb
, text
) {
421 Util
.Debug(">> UI.clipReceive: " + text
.substr(0,40) + "...");
422 $D('VNC_clipboard_text').value
= text
;
423 Util
.Debug("<< UI.clipReceive");
427 connect: function() {
428 var host
, port
, password
;
430 UI
.closeSettingsMenu();
432 host
= $D('VNC_host').value
;
433 port
= $D('VNC_port').value
;
434 password
= $D('VNC_password').value
;
435 if ((!host
) || (!port
)) {
436 throw("Must set host and port");
439 UI
.rfb
.set_encrypt(UI
.getSetting('encrypt'));
440 UI
.rfb
.set_true_color(UI
.getSetting('true_color'));
441 UI
.rfb
.set_local_cursor(UI
.getSetting('cursor'));
442 UI
.rfb
.set_shared(UI
.getSetting('shared'));
443 UI
.rfb
.set_connectTimeout(UI
.getSetting('connectTimeout'));
445 UI
.rfb
.connect(host
, port
, password
);
448 disconnect: function() {
449 UI
.closeSettingsMenu();
454 displayBlur: function() {
455 UI
.rfb
.get_keyboard().set_focused(false);
456 UI
.rfb
.get_mouse().set_focused(false);
459 displayFocus: function() {
460 UI
.rfb
.get_keyboard().set_focused(true);
461 UI
.rfb
.get_mouse().set_focused(true);
464 clipClear: function() {
465 $D('VNC_clipboard_text').value
= "";
466 UI
.rfb
.clipboardPasteFrom("");
469 clipSend: function() {
470 var text
= $D('VNC_clipboard_text').value
;
471 Util
.Debug(">> UI.clipSend: " + text
.substr(0,40) + "...");
472 UI
.rfb
.clipboardPasteFrom(text
);
473 Util
.Debug("<< UI.clipSend");
479 Functions for use of mobile devices native keyboards
480 Added by Chris Gordon
481 http://www.chrisgordon.com.au
485 function showkeyboard(){
486 //Get Current Scroll Position of Browser
487 var scrollx
= (document
.all
)?document
.body
.scrollLeft
:window
.pageXOffset
;
488 var scrolly
= (document
.all
)?document
.body
.scrollTop
:window
.pageYOffset
;
490 //Stop browser zooming on textbox when focus is set.
493 //Focus on hidden textbox to bring up native keyboard.
494 document
.getElementById('keyboardinput').focus();
496 //Set scroll position of browser to the same position it was prior to focus.
497 scroll(scrollx
,scrolly
);
499 //Renable user zooming.
503 function zoomDisable(){
504 //Change viewport meta data to disable zooming.
505 $('head meta[name=viewport]').remove();
506 $('head').prepend('<meta name="viewport" content="user-scalable=0" />');
509 function zoomEnable(){
510 //Change viewport meta data to enable user zooming.
511 $('head meta[name=viewport]').remove();
512 $('head').prepend('<meta name="viewport" content="user-scalable=1" />');