Fixed confusing "Idle" error handling, improved scoping of UI elements and behavior.

This commit is contained in:
Michael Jumper
2011-12-12 20:21:04 -08:00
parent 06189b65bd
commit 3544842514
2 changed files with 332 additions and 283 deletions

View File

@@ -72,254 +72,28 @@
</div>
<!-- Scripts -->
<!-- guacamole-common-js scripts -->
<script type="text/javascript" src="guacamole-common-js/keyboard.js"></script>
<script type="text/javascript" src="guacamole-common-js/mouse.js"></script>
<script type="text/javascript" src="guacamole-common-js/layer.js"></script>
<script type="text/javascript" src="guacamole-common-js/tunnel.js"></script>
<script type="text/javascript" src="guacamole-common-js/guacamole.js"></script>
<script type="text/javascript" src="guacamole-common-js/oskeyboard.js"></script>
<!-- guacamole-default-webapp scripts -->
<script type="text/javascript" src="scripts/interface.js"></script>
<!-- Init -->
<script type="text/javascript"> /* <![CDATA[ */
var display = document.getElementById("display");
// Instantiate client
var guac = new Guacamole.Client(
display,
GuacamoleUI.display,
new Guacamole.HTTPTunnel("tunnel")
);
var menu = document.getElementById("menu");
var logo = document.getElementById("status-logo");
var errorDialog = document.getElementById("errorDialog");
var errorDialogText = document.getElementById("errorText");
var state = document.getElementById("state");
guac.onstatechange = function(clientState) {
switch (clientState) {
case 0:
state.textContent = "Idle."
break;
case 1:
state.textContent = "Connecting...";
break;
case 2:
state.textContent = "Connected, waiting for first update...";
break;
case 3:
display.className = display.className.replace(/guac-loading/, '');
menu.className = "connected";
state.textContent = "Connected.";
shadeMenu();
break;
case 4:
state.textContent = "Disconnecting...";
break;
case 5:
state.textContent = "Disconnected.";
break;
default:
state.textContent = "Unknown";
}
};
// Cache error image (might not be available when error occurs)
var guacErrorImage = new Image();
guacErrorImage.src = "images/noguacamole-logo-24.png";
guac.onname = function(name) {
document.title = name;
};
guac.onerror = function(error) {
guac.disconnect();
menu.className = "error";
display.className += " guac-error";
logo.src = guacErrorImage.src;
errorDialogText.textContent = error;
errorDialog.style.visibility = "visible";
// Show error by desaturating display
var layers = guac.getLayers();
for (var i=0; i<layers.length; i++) {
layers[i].filter(desaturateFilter);
}
// Filter for desaturation
function desaturateFilter(data, width, height) {
for (var i=0; i<data.length; i+=4) {
// Get RGB values
var r = data[i];
var g = data[i+1];
var b = data[i+2];
// Desaturate
var v = Math.max(r, g, b) / 2;
data[i] = v;
data[i+1] = v;
data[i+2] = v;
}
}
};
// Mouse
var mouse = new Guacamole.Mouse(display);
mouse.onmousedown = mouse.onmouseup = mouse.onmousemove =
function(mouseState) {
if (mouseState.y <= 5)
showMenu();
guac.sendMouseState(mouseState);
};
// Keyboard
var keyboard = new Guacamole.Keyboard(document);
function disableKeyboard() {
keyboard.onkeydown = null;
keyboard.onkeyup = null;
}
function enableKeyboard() {
keyboard.onkeydown =
function (keysym) {
guac.sendKeyEvent(1, keysym);
};
keyboard.onkeyup =
function (keysym) {
guac.sendKeyEvent(0, keysym);
};
}
// Enable keyboard by default
enableKeyboard();
// Reconnect button
var reconnect = document.getElementById("reconnect");
reconnect.onclick = function() {
window.location.reload();
};
// Disconnect on close
window.onunload = function() {
guac.disconnect();
};
// Handle clipboard events
var clipboardElement = document.getElementById("clipboard");
clipboardElement.onchange = function() {
var text = clipboardElement.value;
guac.setClipboard(text);
};
// Ignore keypresses when clipboard is focused
clipboardElement.onfocus = function() {
disableKeyboard();
};
// Capture keypresses when clipboard is not focused
clipboardElement.onblur = function() {
enableKeyboard();
};
// Server copy handler
guac.onclipboard = function(data) {
clipboardElement.value = data;
};
// Show/Hide clipboard
var clipboardDiv = document.getElementById("clipboardDiv");
var showClipboard = document.getElementById("showClipboard");
showClipboard.onclick = function() {
var displayed = clipboardDiv.style.display;
if (displayed != "block") {
clipboardDiv.style.display = "block";
showClipboard.innerHTML = "Hide Clipboard";
}
else {
clipboardDiv.style.display = "none";
showClipboard.innerHTML = "Show Clipboard";
clipboardElement.onchange();
}
};
// Show/Hide keyboard
var keyboardContainer = document.getElementById("keyboardContainer");
var showKeyboard = document.getElementById("showKeyboard");
showKeyboard.onclick = function() {
var displayed = keyboardContainer.style.display;
if (displayed != "block") {
keyboardContainer.style.display = "block";
showKeyboard.textContent = "Hide Keyboard";
}
else {
keyboardContainer.style.display = "none";
showKeyboard.textContent = "Show Keyboard";
}
};
// On-screen keyboard
var osKeyboard = new Guacamole.OnScreenKeyboard("layouts/en-us-qwerty.xml");
keyboardContainer.appendChild(osKeyboard);
osKeyboard.setKeyPressedHandler(
function(keysym) {
guac.sendKeyEvent(1, keysym);
}
);
osKeyboard.setKeyReleasedHandler(
function(keysym) {
guac.sendKeyEvent(0, keysym);
}
);
// Send Ctrl-Alt-Delete
var ctrlAltDelete = document.getElementById("ctrlAltDelete");
ctrlAltDelete.onclick = function() {
var KEYSYM_CTRL = 0xFFE3;
var KEYSYM_ALT = 0xFFE9;
var KEYSYM_DELETE = 0xFFFF;
guac.sendKeyEvent(1, KEYSYM_CTRL);
guac.sendKeyEvent(1, KEYSYM_ALT);
guac.sendKeyEvent(1, KEYSYM_DELETE);
guac.sendKeyEvent(0, KEYSYM_DELETE);
guac.sendKeyEvent(0, KEYSYM_ALT);
guac.sendKeyEvent(0, KEYSYM_CTRL);
};
// Logout
var logout = document.getElementById("logout");
logout.onclick = function() {
window.location.href = "logout";
};
// Tie UI to client
GuacamoleUI.attach(guac);
try {
@@ -331,18 +105,9 @@
}
catch (e) {
// TODO: Handle exception ...
GuacamoleUI.showError(e.message);
}
display.onmouseout = function() {
showMenu();
};
display.onmouseover = function() {
shadeMenu();
};
/* ]]> */ </script>
</body>

View File

@@ -1,56 +1,340 @@
var menu_shaded = false;
// UI Definition
var GuacamoleUI = {
var shade_interval = null;
var show_interval = null;
"display": document.getElementById("display"),
"menu" : document.getElementById("menu"),
"logo" : document.getElementById("status-logo"),
"state" : document.getElementById("state"),
function shadeMenu() {
"buttons": {
if (!menu_shaded) {
"showClipboard": document.getElementById("showClipboard"),
"showKeyboard" : document.getElementById("showKeyboard"),
"ctrlAltDelete": document.getElementById("ctrlAltDelete"),
"reconnect" : document.getElementById("reconnect"),
"logout" : document.getElementById("logout")
var step = Math.floor(menu.offsetHeight / 5) + 1;
var offset = 0;
menu_shaded = true;
},
window.clearInterval(show_interval);
shade_interval = window.setInterval(function() {
"containers": {
"error" : document.getElementById("errorDialog"),
"clipboard": document.getElementById("clipboardDiv"),
"keyboard" : document.getElementById("keyboardContainer")
},
offset -= step;
menu.style.top = offset + "px";
"error" : document.getElementById("errorText"),
"clipboard" : document.getElementById("clipboard")
if (offset <= -menu.offsetHeight) {
window.clearInterval(shade_interval);
menu.style.visiblity = "hidden";
}
};
}, 30);
// Constant UI initialization and behavior
(function() {
var menu_shaded = false;
var shade_interval = null;
var show_interval = null;
// Cache error image (might not be available when error occurs)
var guacErrorImage = new Image();
guacErrorImage.src = "images/noguacamole-logo-24.png";
GuacamoleUI.showError = function(error) {
GuacamoleUI.menu.className = "error";
GuacamoleUI.display.className += " guac-error";
GuacamoleUI.logo.src = guacErrorImage.src;
GuacamoleUI.error.textContent = error;
GuacamoleUI.containers.error.style.visibility = "visible";
};
GuacamoleUI.shadeMenu = function() {
if (!menu_shaded) {
var step = Math.floor(GuacamoleUI.menu.offsetHeight / 5) + 1;
var offset = 0;
menu_shaded = true;
window.clearInterval(show_interval);
shade_interval = window.setInterval(function() {
offset -= step;
GuacamoleUI.menu.style.top = offset + "px";
if (offset <= -GuacamoleUI.menu.offsetHeight) {
window.clearInterval(shade_interval);
GuacamoleUI.menu.style.visiblity = "hidden";
}
}, 30);
}
};
GuacamoleUI.showMenu = function() {
if (menu_shaded) {
var step = Math.floor(GuacamoleUI.menu.offsetHeight / 5) + 1;
var offset = -GuacamoleUI.menu.offsetHeight;
menu_shaded = false;
GuacamoleUI.menu.style.visiblity = "";
window.clearInterval(shade_interval);
show_interval = window.setInterval(function() {
offset += step;
if (offset >= 0) {
offset = 0;
window.clearInterval(show_interval);
}
GuacamoleUI.menu.style.top = offset + "px";
}, 30);
}
};
// Show/Hide clipboard
GuacamoleUI.buttons.showClipboard.onclick = function() {
var displayed = GuacamoleUI.containers.clipboard.style.display;
if (displayed != "block") {
GuacamoleUI.containers.clipboard.style.display = "block";
GuacamoleUI.buttons.showClipboard.innerHTML = "Hide Clipboard";
}
else {
GuacamoleUI.containers.clipboard.style.display = "none";
GuacamoleUI.buttons.showClipboard.innerHTML = "Show Clipboard";
GuacamoleUI.clipboard.onchange();
}
};
// Show/Hide keyboard
GuacamoleUI.buttons.showKeyboard.onclick = function() {
var displayed = GuacamoleUI.containers.keyboard.style.display;
if (displayed != "block") {
GuacamoleUI.containers.keyboard.style.display = "block";
GuacamoleUI.buttons.showKeyboard.textContent = "Hide Keyboard";
}
else {
GuacamoleUI.containers.keyboard.style.display = "none";
GuacamoleUI.buttons.showKeyboard.textContent = "Show Keyboard";
}
};
// Logout
GuacamoleUI.buttons.logout.onclick = function() {
window.location.href = "logout";
};
GuacamoleUI.display.onmouseout = function() {
GuacamoleUI.showMenu();
};
GuacamoleUI.display.onmouseover = function() {
GuacamoleUI.shadeMenu();
};
// Reconnect button
GuacamoleUI.buttons.reconnect.onclick = function() {
window.location.reload();
};
// On-screen keyboard
GuacamoleUI.keyboard = new Guacamole.OnScreenKeyboard("layouts/en-us-qwerty.xml");
GuacamoleUI.containers.keyboard.appendChild(GuacamoleUI.keyboard);
})();
// Tie UI events / behavior to a specific Guacamole client
GuacamoleUI.attach = function(guac) {
// Mouse
var mouse = new Guacamole.Mouse(GuacamoleUI.display);
mouse.onmousedown = mouse.onmouseup = mouse.onmousemove =
function(mouseState) {
if (mouseState.y <= 5)
GuacamoleUI.showMenu();
guac.sendMouseState(mouseState);
};
// Keyboard
var keyboard = new Guacamole.Keyboard(document);
function disableKeyboard() {
keyboard.onkeydown = null;
keyboard.onkeyup = null;
}
}
function enableKeyboard() {
keyboard.onkeydown =
function (keysym) {
guac.sendKeyEvent(1, keysym);
};
function showMenu() {
if (menu_shaded) {
var step = Math.floor(menu.offsetHeight / 5) + 1;
var offset = -menu.offsetHeight;
menu_shaded = false;
menu.style.visiblity = "";
window.clearInterval(shade_interval);
show_interval = window.setInterval(function() {
offset += step;
if (offset >= 0) {
offset = 0;
window.clearInterval(show_interval);
}
menu.style.top = offset + "px";
}, 30);
keyboard.onkeyup =
function (keysym) {
guac.sendKeyEvent(0, keysym);
};
}
}
// Enable keyboard by default
enableKeyboard();
// Handle client state change
guac.onstatechange = function(clientState) {
switch (clientState) {
// Idle
case 0:
GuacamoleUI.state.textContent = "Idle."
break;
// Connecting
case 1:
GuacamoleUI.state.textContent = "Connecting...";
break;
// Connected + waiting
case 2:
GuacamoleUI.state.textContent = "Connected, waiting for first update...";
break;
// Connected
case 3:
GuacamoleUI.display.className =
GuacamoleUI.display.className.replace(/guac-loading/, '');
GuacamoleUI.menu.className = "connected";
GuacamoleUI.state.textContent = "Connected.";
GuacamoleUI.shadeMenu();
break;
// Disconnecting
case 4:
GuacamoleUI.state.textContent = "Disconnecting...";
break;
// Disconnected
case 5:
GuacamoleUI.state.textContent = "Disconnected.";
break;
// Unknown status code
default:
GuacamoleUI.state.textContent = "Unknown";
}
};
// Name instruction handler
guac.onname = function(name) {
document.title = name;
};
// Error handler
guac.onerror = function(error) {
// Disconnect, if connected
guac.disconnect();
// Display error message
GuacamoleUI.showError(error);
// Show error by desaturating display
var layers = guac.getLayers();
for (var i=0; i<layers.length; i++) {
layers[i].filter(desaturateFilter);
}
// Filter for desaturation
function desaturateFilter(data, width, height) {
for (var i=0; i<data.length; i+=4) {
// Get RGB values
var r = data[i];
var g = data[i+1];
var b = data[i+2];
// Desaturate
var v = Math.max(r, g, b) / 2;
data[i] = v;
data[i+1] = v;
data[i+2] = v;
}
}
};
// Disconnect on close
window.onunload = function() {
guac.disconnect();
};
// Handle clipboard events
GuacamoleUI.clipboard.onchange = function() {
var text = GuacamoleUI.clipboard.value;
guac.setClipboard(text);
};
// Ignore keypresses when clipboard is focused
GuacamoleUI.clipboard.onfocus = function() {
disableKeyboard();
};
// Capture keypresses when clipboard is not focused
GuacamoleUI.clipboard.onblur = function() {
enableKeyboard();
};
// Server copy handler
guac.onclipboard = function(data) {
GuacamoleUI.clipboard.value = data;
};
GuacamoleUI.keyboard.setKeyPressedHandler(
function(keysym) {
guac.sendKeyEvent(1, keysym);
}
);
GuacamoleUI.keyboard.setKeyReleasedHandler(
function(keysym) {
guac.sendKeyEvent(0, keysym);
}
);
// Send Ctrl-Alt-Delete
GuacamoleUI.buttons.ctrlAltDelete.onclick = function() {
var KEYSYM_CTRL = 0xFFE3;
var KEYSYM_ALT = 0xFFE9;
var KEYSYM_DELETE = 0xFFFF;
guac.sendKeyEvent(1, KEYSYM_CTRL);
guac.sendKeyEvent(1, KEYSYM_ALT);
guac.sendKeyEvent(1, KEYSYM_DELETE);
guac.sendKeyEvent(0, KEYSYM_DELETE);
guac.sendKeyEvent(0, KEYSYM_ALT);
guac.sendKeyEvent(0, KEYSYM_CTRL);
};
};