Files
noVNC/include/ui.js
Joel Martin b70ce07706 Fix window/document sizing in firefox.
Another firefox issue is that height: 100% is calculated as 100% of
the containing element even when the containing element is the window.
This means that the size of any sibling element shifts the window size
down by that much and causes the vertical scroll bars to appear. This
doesn't happen in Chrome.

- So instead, put a pad element inside the noVNC_screen element that
  is the size of the control bar. This is hidden by the control bar,
  however, it causes things to be sized correctly.

- Also, rename noVNC_defaultScreen to noVNC_logo.

- Clean some style specification out of the HTML.
2011-09-13 13:14:11 -05:00

531 lines
15 KiB
JavaScript

/*
* noVNC: HTML5 VNC client
* Copyright (C) 2011 Joel Martin
* Licensed under LGPL-3 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
"use strict";
/*jslint white: false, browser: true */
/*global window, $D, Util, WebUtil, RFB, Display */
var UI = {
settingsOpen : false,
connSettingsOpen : true,
clipboardOpen: false,
// Render default UI and initialize settings menu
load: function() {
var html = '', i, sheet, sheets, llevels;
// Stylesheet selection dropdown
sheet = WebUtil.selectStylesheet();
sheets = WebUtil.getStylesheets();
for (i = 0; i < sheets.length; i += 1) {
UI.addOption($D('noVNC_stylesheet'),sheets[i].title, sheets[i].title);
}
// Logging selection dropdown
llevels = ['error', 'warn', 'info', 'debug'];
for (i = 0; i < llevels.length; i += 1) {
UI.addOption($D('noVNC_logging'),llevels[i], llevels[i]);
}
// Settings with immediate effects
UI.initSetting('logging', 'warn');
WebUtil.init_logging(UI.getSetting('logging'));
UI.initSetting('stylesheet', 'default');
WebUtil.selectStylesheet(null);
// call twice to get around webkit bug
WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
/* Populate the controls if defaults are provided in the URL */
UI.initSetting('host', '');
UI.initSetting('port', '');
UI.initSetting('password', '');
UI.initSetting('encrypt', false);
UI.initSetting('true_color', true);
UI.initSetting('cursor', false);
UI.initSetting('shared', true);
UI.initSetting('connectTimeout', 2);
UI.rfb = RFB({'target': $D('noVNC_canvas'),
'onUpdateState': UI.updateState,
'onClipboard': UI.clipReceive});
// Unfocus clipboard when over the VNC area
//$D('VNC_screen').onmousemove = function () {
// var keyboard = UI.rfb.get_keyboard();
// if ((! keyboard) || (! keyboard.get_focused())) {
// $D('VNC_clipboard_text').blur();
// }
// };
// Show mouse selector buttons on touch screen devices
if ('ontouchstart' in document.documentElement) {
$D('noVNC_mobile_buttons').style.display = "inline";
UI.setMouseButton();
window.scrollTo(0, 1);
}
//iOS Safari does not support CSS position:fixed.
//This detects iOS devices and enables javascript workaround.
if ((navigator.userAgent.match(/iPhone/i)) ||
(navigator.userAgent.match(/iPod/i)) ||
(navigator.userAgent.match(/iPad/i))) {
UI.setOnscroll();
UI.setResize();
}
$D('noVNC_host').focus();
},
// Read form control compatible setting from cookie
getSetting: function(name) {
var val, ctrl = $D('noVNC_' + name);
val = WebUtil.readCookie(name);
if (ctrl.type === 'checkbox') {
if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) {
val = false;
} else {
val = true;
}
}
return val;
},
// Update cookie and form control setting. If value is not set, then
// updates from control to current cookie setting.
updateSetting: function(name, value) {
var i, ctrl = $D('noVNC_' + name);
// Save the cookie for this session
if (typeof value !== 'undefined') {
WebUtil.createCookie(name, value);
}
// Update the settings control
value = UI.getSetting(name);
if (ctrl.type === 'checkbox') {
ctrl.checked = value;
} else if (typeof ctrl.options !== 'undefined') {
for (i = 0; i < ctrl.options.length; i += 1) {
if (ctrl.options[i].value === value) {
ctrl.selectedIndex = i;
break;
}
}
} else {
/*Weird IE9 error leads to 'null' appearring
in textboxes instead of ''.*/
if (value === null) {
value = "";
}
ctrl.value = value;
}
},
// Save control setting to cookie
saveSetting: function(name) {
var val, ctrl = $D('noVNC_' + name);
if (ctrl.type === 'checkbox') {
val = ctrl.checked;
} else if (typeof ctrl.options !== 'undefined') {
val = ctrl.options[ctrl.selectedIndex].value;
} else {
val = ctrl.value;
}
WebUtil.createCookie(name, val);
//Util.Debug("Setting saved '" + name + "=" + val + "'");
return val;
},
// Initial page load read/initialization of settings
initSetting: function(name, defVal) {
var val;
// Check Query string followed by cookie
val = WebUtil.getQueryVar(name);
if (val === null) {
val = WebUtil.readCookie(name, defVal);
}
UI.updateSetting(name, val);
//Util.Debug("Setting '" + name + "' initialized to '" + val + "'");
return val;
},
// Toggle the settings menu:
// On open, settings are refreshed from saved cookies.
// On close, settings are applied
clickSettingsMenu: function() {
if (UI.settingsOpen) {
UI.settingsApply();
UI.closeSettingsMenu();
} else {
UI.updateSetting('encrypt');
UI.updateSetting('true_color');
if (UI.rfb.get_display().get_cursor_uri()) {
UI.updateSetting('cursor');
} else {
UI.updateSetting('cursor', false);
$D('noVNC_cursor').disabled = true;
}
UI.updateSetting('shared');
UI.updateSetting('connectTimeout');
UI.updateSetting('stylesheet');
UI.updateSetting('logging');
UI.openSettingsMenu();
}
},
// Open menu
openSettingsMenu: function() {
if (UI.clipboardOpen == true) {
UI.showClipboard();
}
//Close connection settings if open
if (UI.connSettingsOpen == true) {
UI.connectPanelbutton();
}
$D('noVNC_Settings').style.display = "block";
UI.settingsOpen = true;
},
// Close menu (without applying settings)
closeSettingsMenu: function() {
$D('noVNC_Settings').style.display = "none";
UI.settingsOpen = false;
},
// Disable/enable controls depending on connection state
settingsDisabled: function(disabled, rfb) {
//Util.Debug(">> settingsDisabled");
$D('noVNC_encrypt').disabled = disabled;
$D('noVNC_true_color').disabled = disabled;
if (rfb && rfb.get_display() && rfb.get_display().get_cursor_uri()) {
$D('noVNC_cursor').disabled = disabled;
} else {
UI.updateSetting('cursor', false);
$D('noVNC_cursor').disabled = true;
}
$D('noVNC_shared').disabled = disabled;
$D('noVNC_connectTimeout').disabled = disabled;
//Util.Debug("<< settingsDisabled");
},
// Save/apply settings when 'Apply' button is pressed
settingsApply: function() {
//Util.Debug(">> settingsApply");
UI.saveSetting('encrypt');
UI.saveSetting('true_color');
if (UI.rfb.get_display().get_cursor_uri()) {
UI.saveSetting('cursor');
}
UI.saveSetting('shared');
UI.saveSetting('connectTimeout');
UI.saveSetting('stylesheet');
UI.saveSetting('logging');
// Settings with immediate (non-connected related) effect
WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
WebUtil.init_logging(UI.getSetting('logging'));
//Util.Debug("<< settingsApply");
},
setPassword: function() {
UI.rfb.sendPassword($D('noVNC_password').value);
//Reset connect button.
$D('noVNC_connect_button').value = "Connect";
$D('noVNC_connect_button').onclick = UI.Connect;
//Hide connection panel.
UI.connectPanelbutton();
return false;
},
sendCtrlAltDel: function() {
UI.rfb.sendCtrlAltDel();
},
setMouseButton: function(num) {
var b, blist = [1,2,4], button,
mouse = UI.rfb.get_mouse();
if (typeof num === 'undefined') {
// Show the default
num = mouse.get_touchButton();
} else if (num === mouse.get_touchButton()) {
// Set all buttons off (no clicks)
mouse.set_touchButton(0);
num = 0;
} else {
// Turn on one button
mouse.set_touchButton(num);
}
for (b = 0; b < blist.length; b++) {
button = $D('noVNC_mouse_button' + blist[b]);
if (blist[b] === num) {
button.style.backgroundColor = "black";
button.style.color = "lightgray";
} else {
button.style.backgroundColor = "";
button.style.color = "";
}
}
},
updateState: function(rfb, state, oldstate, msg) {
var s, sb, c, cad, klass;
s = $D('noVNC_status');
sb = $D('noVNC_status_bar');
c = $D('connectPanelbutton');
cad = $D('sendCtrlAltDelButton');
switch (state) {
case 'failed':
case 'fatal':
c.disabled = true;
cad.style.display = "none";
UI.settingsDisabled(true, rfb);
klass = "noVNC_status_error";
break;
case 'normal':
c.value = "Disconnect";
c.onclick = UI.disconnect;
c.disabled = false;
cad.style.display = "block";
UI.settingsDisabled(true, rfb);
klass = "noVNC_status_normal";
break;
case 'disconnected':
$D('noVNC_logo').style.display = "block";
c.value = "Connection";
c.onclick = UI.connectPanelbutton;
case 'loaded':
c.value = "Connection";
c.onclick = UI.connectPanelbutton;
c.disabled = false;
cad.style.display = "none";
UI.settingsDisabled(false, rfb);
klass = "noVNC_status_normal";
break;
case 'password':
UI.connectPanelbutton();
$D('noVNC_connect_button').value = "Send Password";
$D('noVNC_connect_button').onclick = UI.setPassword;
$D('noVNC_password').focus();
c.disabled = false;
cad.style.display = "none";
UI.settingsDisabled(true, rfb);
klass = "noVNC_status_warn";
break;
default:
c.disabled = true;
cad.style.display = "none";
UI.settingsDisabled(true, rfb);
klass = "noVNC_status_warn";
break;
}
if (typeof(msg) !== 'undefined') {
s.setAttribute("class", klass);
sb.setAttribute("class", klass);
s.innerHTML = msg;
}
},
clipReceive: function(rfb, text) {
Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
$D('noVNC_clipboard_text').value = text;
Util.Debug("<< UI.clipReceive");
},
connect: function() {
var host, port, password;
UI.closeSettingsMenu();
UI.connectPanelbutton();
host = $D('noVNC_host').value;
port = $D('noVNC_port').value;
password = $D('noVNC_password').value;
if ((!host) || (!port)) {
throw("Must set host and port");
}
UI.rfb.set_encrypt(UI.getSetting('encrypt'));
UI.rfb.set_true_color(UI.getSetting('true_color'));
UI.rfb.set_local_cursor(UI.getSetting('cursor'));
UI.rfb.set_shared(UI.getSetting('shared'));
UI.rfb.set_connectTimeout(UI.getSetting('connectTimeout'));
UI.rfb.connect(host, port, password);
//Close dialog.
setTimeout(UI.setBarPosition, 100);
$D('noVNC_logo').style.display = "none";
},
disconnect: function() {
UI.closeSettingsMenu();
UI.rfb.disconnect();
$D('noVNC_logo').style.display = "block";
UI.connSettingsOpen = false;
UI.connectPanelbutton();
},
displayBlur: function() {
UI.rfb.get_keyboard().set_focused(false);
UI.rfb.get_mouse().set_focused(false);
},
displayFocus: function() {
UI.rfb.get_keyboard().set_focused(true);
UI.rfb.get_mouse().set_focused(true);
},
clipClear: function() {
$D('noVNC_clipboard_text').value = "";
UI.rfb.clipboardPasteFrom("");
},
clipSend: function() {
var text = $D('noVNC_clipboard_text').value;
Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
UI.rfb.clipboardPasteFrom(text);
Util.Debug("<< UI.clipSend");
},
showClipboard: function() {
//Close settings if open
if (UI.settingsOpen == true) {
UI.closeSettingsMenu();
}
//Close connection settings if open
if (UI.connSettingsOpen == true) {
UI.connectPanelbutton();
}
//Toggle Connection Panel
if (UI.clipboardOpen == true) {
$D('noVNC_clipboard').style.display = "none";
UI.clipboardOpen = false;
} else {
$D('noVNC_clipboard').style.display = "block";
UI.clipboardOpen = true;
}
},
showKeyboard: function() {
//Get Current Scroll Position
var scrollx =
(document.all)?document.body.scrollLeft:window.pageXOffset;
var scrolly =
(document.all)?document.body.scrollTop:window.pageYOffset;
//Stop browser zooming on textbox.
UI.zoomDisable();
$D('keyboardinput').focus();
scroll(scrollx,scrolly);
//Renable user zoom.
UI.zoomEnable();
},
zoomDisable: function() {
//Change viewport meta data to disable zooming.
UI.changeViewportMeta("user-scalable=0");
},
zoomEnable: function(){
//Change viewport meta data to enable user zooming.
UI.changeViewportMeta("user-scalable=1");
},
changeViewportMeta: function (newattributes) {
// First, get the array of meta-tag elements
var metatags = document.getElementsByTagName("meta");
// Update only the Viewport meta tag
for (var cnt = 0; cnt < metatags.length; cnt++)
{
var name = metatags[cnt].getAttribute("name");
var content = metatags[cnt].getAttribute("content");
// Update the Viewport meta tag
if (metatags[cnt].getAttribute("name") == "viewport") {
metatags[cnt].setAttribute("content", newattributes);
}
}
},
//iOS < Version 5 does not support position fixed. Javascript workaround:
setOnscroll: function() {
window.onscroll = function() {
UI.setBarPosition();
};
},
setResize: function () {
window.onResize = function() {
UI.setBarPosition();
};
},
//Helper to add options to dropdown.
addOption: function(selectbox,text,value )
{
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
},
setBarPosition: function() {
$D('noVNC-control-bar').style.top = (window.pageYOffset) + 'px';
$D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px';
$D('noVNC_buttons_right').style.right = 0 + 'px';
var vncwidth = $D('noVNC_screen').style.offsetWidth;
$D('noVNC-control-bar').style.width = vncwidth + 'px';
},
connectPanelbutton: function() {
//Close connection settings if open
if (UI.settingsOpen == true) {
UI.closeSettingsMenu();
}
if (UI.clipboardOpen == true) {
UI.showClipboard();
}
//Toggle Connection Panel
if (UI.connSettingsOpen == true) {
$D('noVNC_controls').style.display = "none";
UI.connSettingsOpen = false;
} else {
$D('noVNC_controls').style.display = "block";
UI.connSettingsOpen = true;
$D('noVNC_host').focus();
}
}
};